I am developing one app which is based on tabbarcontroller.In one view Controller i want to hidden the tabbarController instead of that i want to show toolbar for that purpose i wrote the following code
//tabBAr hidden
[self.tabBarController.tabBar setHidden:YES];
//creation of tool bar
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
tb = [[UIToolbar alloc] init];
//[tb setBackgroundImage:[UIImage imageNamed:#"tabbar.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
tb.tintColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
if ([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone)
{
tb.frame = CGRectMake(0, delegate.window.frame.size.height-50, 320, 44);
}
else
{
tb.frame = CGRectMake(0, delegate.window.frame.size.height-70, 768, 44);
}
[delegate.window addSubview:tb];
But problem is in iPad i want to change orientation of toolbar but it does not change it always takes portrait width and height.
Use notification to detect the device orientation like the following.
// Start Orientation //
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//NSLog(#"Vertical");
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//NSLog(#"Horizontal");
}
}
// End Orientation //
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
Somebody has kindly written this notification code somewhere. I didn't write it.
use viewWillLayoutSubViews method and add code to setFrame of toolbar in that method
ex:
- (void) viewWillLayoutSubviews
{
[toolBar setFrmae:CGRectMake(self.view.bounds.origin.x, self.view.bounds.size.height - 44, self.view.bounds.size.width, 44)];
}
Related
I am using MBProgressHud to show a loading indicator on a splash view but this does not change with device orientation. My code is:
splashView = [[UIImageView alloc] initWithFrame:self.window.frame];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
splashView.image = [UIImage imageNamed:#"DefaultPad.png"];
}
else
{
splashView.image = [UIImage imageNamed:#"Default.png"];
}
hud = [[MBProgressHUD alloc]initWithView:splashView];
[splashView addSubview:hud];
hud.userInteractionEnabled=NO;
hud.labelText = #"Loading...";
[hud show:YES];
[self.window addSubview:splashView];
[self performSelector:#selector(Load_FirstView) withObject:nil afterDelay:3];
[self.window makeKeyAndVisible];
and I have changed the line in MBProgressHud.m file from
- (void)deviceOrientationDidChange:(NSNotification *)notification {
NSLog(#"in device orientation ");
UIView *superview = self.superview;
if (!superview) {
return;
} else if ([superview isKindOfClass:[UIWindow class]]) { // here changes have done
[self setTransformForCurrentOrientation:YES];
} else {
self.bounds = self.superview.bounds;
[self setNeedsDisplay];
}
}
to:
- (void)deviceOrientationDidChange:(NSNotification *)notification {
NSLog(#"in device orientation ");
UIView *superview = self.superview;
if (!superview) {
return;
} else if ([superview isKindOfClass:[UIImageView class]]) {
[self setTransformForCurrentOrientation:YES];
} else {
self.bounds = self.superview.bounds;
[self setNeedsDisplay];
}
}
How can I get the loading indicator to rotate with device orientation?
In MBProgressHUD.m I changed
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
to
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
The orientation notification had been received, but the statusBar had not rotated yet.
Try This:-
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
//code for portrait
[hud release];
hud = [[MBProgressHUD alloc]initWithView:splashView];
}
else
{
//code for Landscape
[hud release];
hud = [[MBProgressHUD alloc]initWithView:splashView];
}
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
if it does not work..
you can change the UIDeviceOrientationDidChangeNotification with UIApplicationDidChangeStatusBarOrientationNotificationin the source code of MBProgressHUD:-
- (id)initWithView:(UIView *)view {
// Let's check if the view is nil (this is a common error when using the windw initializer above)
if (!view) {
[NSException raise:#"MBProgressHUDViewIsNillException"
format:#"The view used in the MBProgressHUD initializer is nil."];
}
id me = [self initWithFrame:view.bounds];
// We need to take care of rotation ourselfs if we're adding the HUD to a window
if ([view isKindOfClass:[UIWindow class]]) {
[self setTransformForCurrentOrientation:NO];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:)
name:UIDeviceOrientationDidChangeNotification object:nil];
return me;
}
In the above code change UIDeviceOrientationDidChangeNotificationwith UIApplicationDidChangeStatusBarOrientationNotification.
It is just a work-around as rotation issue was always there with MBProgressHud .
I Guess MBProgressHud is giving a lo of problems , you should instead switch to svprogresshud as it handles orientations well
I'm doing a bit of AR work here and one of the biggest problem right now is one of my UIView will not respond to any frame settings I make to it.
The code is very similar to this. I've made a few major changes to incorporate into my project:
nurse.site11.com/JaredCrawford-iWVU-632a9a0/Libraries/ARKit/AugmentedRealityController.m
"displayView" is used as a custom UIView that is passed to UIImagePickerController's setCameraOverlayView: method.
Now in the initWithViewController method of that AugmentedRealityController.m file, I have tried setting the displayView = [[UIView alloc] initWithFrame:CGRectMakeFrame(0, 0, 480, 320)];
The problem is, even if I set it to displayView = [[UIView alloc] initWithFrame:CGRectMakeFrame(0, 0, 100, 100)]; the view still remains full screen 320 x 480 BUT only for the first time the Augmented Reality view appeared. Subsequent times that the AR view appears, the code works.
I am not sure what the heck is going on and why setting the frame of the displayView not affecting the view at all FOR THE FIRST TIME it is shown.
I'm hoping someone else has experienced this problem before and possibly solved it.
This is my code:
- (id)initWithViewController:(UIViewController *)vc
{
coordinates = [[NSMutableArray alloc] init];
coordinateViews = [[NSMutableArray alloc] init];
latestHeading = -1.0f;
debugView = nil;
[self setRootViewController: vc];
[self setDebugMode:NO];
[self setMaximumScaleDistance: 0.0];
[self setMinimumScaleFactor: 1.0];
[self setScaleViewsBasedOnDistance: YES];
[self setRotateViewsBasedOnPerspective: YES];
[self setMaximumRotationAngle: M_PI / 6.0];
//CGRect screenRect = [[UIScreen mainScreen] bounds];
NSLog(#"inside initWithViewController");
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationPortrait)
{
NSLog(#"Orientation portrait");
}
else if(orientation == UIDeviceOrientationLandscapeRight)
{
NSLog(#"orientation right");
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
[self setCurrentOrientation:UIDeviceOrientationLandscapeRight];
}
else if(orientation == UIDeviceOrientationPortraitUpsideDown)
{
NSLog(#"orientation upsidedown");
}
else if(orientation == UIDeviceOrientationLandscapeLeft){
NSLog(#"orientation left");
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[self setCurrentOrientation:UIDeviceOrientationLandscapeLeft];
}
//[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
//NSLog(#"In AR view, device orientation = %#", [[UIDevice currentDevice] orientation]);
//[self setDisplayView: [[UIView alloc] initWithFrame: screenRect]];
//[self setCurrentOrientation:UIDeviceOrientationLandscapeRight];
displayView = [[UIView alloc] initWithFrame:CGRectMake(-80, 80, 480, 320)];
[displayView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5]];
NSLog(#"displayView x = %f", displayView.frame.origin.x);
NSLog(#"displayView y = %f", displayView.frame.origin.y);
NSLog(#"displayView width = %f", displayView.frame.size.width);
NSLog(#"displayView height = %f", displayView.frame.size.height);
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[self rootViewController] setView:displayView];
//[[self rootViewController] setView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 480, 320)]];
//[[rootViewController view] setBackgroundColor:[UIColor blueColor]];
CLLocation *newCenter = [[CLLocation alloc] initWithLatitude:37.41711 longitude:-122.02528];
[self setCenterLocation: newCenter];
[newCenter release];
[self startListening];
[self deviceOrientationUpdate];
startLocation = nil;
i = 0;
objImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
//[objImageView setBackgroundColor:[UIColor blueColor]];
blnHasRotated = NO;
return self;
}
The full code can be seen here: pastebin.com/g0eXJaPq
I have a simple UIWebView that I've added to my UIViewController in the viewDidLoad method:
CGRect rect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
self.webView = [[UIWebView alloc] initWithFrame:rect];
self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.webView];
And it looks great, but when I rotate the phone, the width and height remain the same so now it's too wide for the update view frame. I also tried using self.view.bounds, but it didn't make any difference.
So how do you ensure that a view that is fullscreen on load, stays the same size when rotated? (without using IB)
What you are doing is correct & should work in most scenarios. But since I have no idea about your View Stack. I will suggest a sure shot way -
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
CGRect rect;
if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft||toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
rect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
else
{
//some other dimensions.
}
self.webView = [[UIWebView alloc] initWithFrame:rect];
}
Because web view not called only once it need to be called again
to set the new frame
self.webView = [[UIWebView alloc] initWithFrame:rect];
so you have to register notification in viwewillappear or viewdidload
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(viewBecamePortrait:) name:#"orientationIsPortrait" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(viewBecameLandscape:) name:#"orientationIsLandscape" object:nil];
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
NSNotification* notification = [NSNotification notificationWithName:#"orientationIsPortrait" object:self];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}else {
NSNotification* notification = [NSNotification notificationWithName:#"orientationIsLandscape" object:self];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}
}
Then implement
-(void)viewBecameLandscape:(id)sender{
if(webview){
[webview.setframe(cgrectmake(x,y,width,height))];
}
}
-(void)viewBecamePortrait:(id)sender{
}
I am creating a application in which I can need to play a video which I do by mpmovieplayer controller .Now i nee to do this for both orientation .But the frame doesnt get set properly .
The code is as follws
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[self shouldAutorotateToInterfaceOrientation:[UIDevice currentDevice].orientation];
NSURL *temp = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Floating" ofType:#"mp4"]];
mpviewController = [[MPMoviePlayerViewController alloc] initWithContentURL:temp];
mpviewController.view.frame = CGRectMake(0, 0, 768, 1024);
mpviewController.view.backgroundColor = [UIColor clearColor];
mpviewController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
mpviewController.view.userInteractionEnabled= NO;
mpviewController.moviePlayer.fullscreen= YES;
mpviewController.moviePlayer.controlStyle = MPMovieControlStyleNone;
[[mpviewController moviePlayer] play];
[self.view addSubview:mpviewController.view];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
currentOrientation = interfaceOrientation;
//[self SetInterface];
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
mpviewController.view.frame = CGRectMake(0, 0, 768, 1024);
else if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight)
mpviewController.view.frame = CGRectMake(0, 0, 1024, 768);
return YES;
}
I dont know where I am wrong.Please let me know for any chages to make in code. So as to get proper orientation.
Ragards Abhi
First
I believe you don't need to resize the mpviewController as it will resize it self alone.
you should only set the -
Second
In the shouldAutorotateToInterfaceOrientation you only set the supported directions in shouldAutorotateToInterfaceOrientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
If it dose not do it you change the view properties in -
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)){
//do what you want for portrait
}else{
//do what you want for landscape
}
}
you should only return either YES or NO in shouldAutorotateToInterfaceOrientation: method, it's called by framework only to get the information about the supported orientation in your controller, Read the apple documentation for the same.
you need to register for the orientation change notifictaion
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
Implement your orientationChanged: method.
//********** ORIENTATION CHANGED **********
- (void) orientationChanged:(NSNotification *)note
{
NSLog(#"Orientation has changed: %d", [[note object] orientation]);
//Put your code here from shouldAutorotateToInterfaceOrientation:
}
Not forget it to remove .
[[NSNotificationCenter defaultCenter] removeObserver:self];
Here are some link
Device orientation - autorotate?
Orientation Changed Notification
No need to change any codings .. simple insert the following codings to the application , it will automatically detect the orientation...
UINavigationBar *bar = [self.navigationController navigationBar];
[bar setTintColor:[UIColor blackColor]];
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"sharkdivertrailer" ofType:#"mp4"];
NSURL *movieURL = [[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.view.frame = CGRectMake(184, 200, 400, 300);
[theMovie play];
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
I have a UIViewController that I'm using to control a "pop-up" view for viewing images throughout my application. It supports autorotation, as it automatically sizes the image to fit properly regardless of orientation. This works perfectly, but only the first time I initialize and display the view controller. When it closes, I am removing the UIView from my view hierarchy and releasing the view controller - but the next time I instantiate and add it to my view hierarchy, it stops receiving the -shouldAutorotateToInterfaceOrientation messages when the phone is rotated.
This is how I instantiate and display it:
popupVC = [[PopupVC alloc] init];
[popupVC viewWillAppear:NO];
[[[UIApplication sharedApplication] keyWindow] addSubview:popupVC.view];
[popupVC viewDidAppear:NO];
this is how I remove/release it when it's finished:
[popupVC viewWillDisappear:NO];
[popupVC.view removeFromSuperview];
[popupVC viewDidDisappear:NO];
[popupVC release];
popupVC = nil;
I've tried looping through [[UIApplication sharedApplication] keyWindow] subviews to see if somehow my popup view isn't on top, but it always is. And it has a different address each time so I do know that it's a different instance of the view controller class.
As requested, here is the complete loadView method from PopupVC:
- (void)loadView {
UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
myView.backgroundColor = self.overlayColor;
myView.autoresizesSubviews = NO;
myView.hidden = YES;
myView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.view = myView;
[myView release];
_isVisible = NO;
UIView *myMaskView = [[UIView alloc] initWithFrame:self.view.bounds];
myMaskView.backgroundColor = [UIColor clearColor];
myMaskView.clipsToBounds = YES;
myMaskView.hidden = YES;
myMaskView.autoresizesSubviews = NO;
myMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myMaskView];
self.imageMaskView = myMaskView;
[myMaskView release];
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
myImageView.center = self.view.center;
myImageView.hidden = NO;
myImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
[self.imageMaskView addSubview:myImageView];
self.imageView = myImageView;
[myImageView release];
UIButton *myImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
myImageButton.frame = self.view.frame;
myImageButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
[myImageButton addTarget:self action:#selector(clickImage:) forControlEvents:UIControlEventTouchUpInside];
[self.imageMaskView addSubview:myImageButton];
self.imageButton = myImageButton;
UIActivityIndicatorView *myActivityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
myActivityView.hidden = YES;
[self.view addSubview:myActivityView];
myActivityView.center = self.view.center;
self.activityView = myActivityView;
[myActivityView release];
}
The shouldAutorotateToInterfaceOrientation handler isn't the place for custom code to respond to rotation events. It's purpose is just to tell the OS that your view controller can rotate. If you want to have custom code to handle the rotation events you should overide - didRotateFromInterfaceOrientation or one of the other similar callback methods depending on your needs:
willRotateToInterfaceOrientation:duration:
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
didAnimateFirstHalfOfRotationToInterfaceOrientation:
willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
See Autorotating Views in the developer docs.
I think that might be a bug in the new OS 3.0. A workaround to this would be to use NSNotificationCenter after turning on beginGeneratingDeviceOrientationNotifications.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void) receivedRotate: (NSNotification *) notification {
DebugLog(#"ORIENTATION CHANGE");
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if(interfaceOrientation == UIDeviceOrientationPortrait) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
self.view.bounds = CGRectMake(0, 0, 320, 480);
}
else if(interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0, 0, 480, 320);
}
else if(interfaceOrientation == UIDeviceOrientationLandscapeRight) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
self.view.bounds = CGRectMake(0, 0, 480, 320);
}
}
My problem is that I get the rotation event for my rootViewController, but as soon as I launch my second viewController, it won't get any signals except motion (shaking) and touch. Is that the same issue as the original post -- it is certainly similiar??
I followed-up with above recommendation and I don't have the selector coded correctly so it throws an exception as soon as I try to rotate. Meanwhile, I found this other discussion on the web which confirms that the problem was introduced in 3.0.
link text