I'm rotating a view similar to tje iTunes app. In portrait is a tableview and in landscape is photo viewver.
When I return from landscape to portrait I try to recover the navigationbar but instead get a distorted tableview, and no navigation bar.
This is what I do:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
BOOL restoreNav = NO;
if ((toInterfaceOrientation == UIInterfaceOrientationPortrait) ||
(toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)) {
[self inPortrait];
restoreNav = YES;
} else {
[self inLandscape];
}
if (self.landscape)
{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
self.view = self.portrait;
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
self.view = self.landscape;
}
else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
self.view = self.portrait;
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscape;
}
[[self.navigationController view] setFrame: [[UIScreen mainScreen] bounds]];
} else {
self.navigationController.navigationBarHidden = NO;
}
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
I found a semi-fix for this in http://www.iphonedevsdk.com/forum/iphone-sdk-development/3262-horrible-drawing-after-hiding-navigationbar.html
This is the relevant code:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
//total hack - to fix the bug where the screen layout is shagged if the device orientation
//is changed when the navigation is hidden
if ([self.navigationController isNavigationBarHidden])
{
[self.navigationController setNavigationBarHidden:NO animated:NO];
[self.navigationController setNavigationBarHidden:TRUE animated:NO];
}
}
However, is messy again if a show up the nav bar.
Related
I am using tab bar controller in my iPhone app having 4 tabs. I have written code for both orientations.
The problem is when I switch my tabs from portrait to landscape view I'm having trouble.For eg. if I'm in tab1 landscape mode and now I switch my tab and move to tab2 landscape mode but i can see portrait setting of that particular view and not the landscape view.
The code so far on my launch view controller that contains the tab bar controller is as follows :
-(void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
if (self.interfaceOrientation==UIInterfaceOrientationLandscapeLeft)
{
[self rotatingLandscape];
}
else if (self.interfaceOrientation==UIInterfaceOrientationLandscapeRight)
{
[self rotatingLandscape];
}
if (self.interfaceOrientation==UIInterfaceOrientationPortrait)
{
[self RotatingPotrait];
}
else if (self.interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown)
{
[self RotatingPotrait];
}
[super viewWillAppear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation==UIInterfaceOrientationPortrait)
{
rotate=YES;
[self RotatingPotrait];
}
if (interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown)
{
rotate=YES;
[self RotatingPotrait];
}
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
rotate=NO;
[self rotatingLandscape];
}
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
rotate=NO;
[self rotatingLandscape];
}
return YES;
}
-(void)rotatingLandscape
{
int selIndex = [self.tabBarController selectedIndex];
if (selIndex == 0)
{
[view1p rotatingLandscape];
}
else if (selIndex == 1)
{
[view2 rotatingLandscape];
}
else if (selIndex == 2)
{
[view3 rotatingLandscape];
}
else if (selIndex == 3)
{
[view4 rotatingLandscape];
}
self.tabBarController.view.frame=CGRectMake(0, 0, 480, 300);
}
-(void)RotatingPotrait
{
int selIndex = [self.tabBarController selectedIndex];
if (selIndex == 0)
{
[view1p RotatingPotrait];
}
else if (selIndex == 1)
{
[view2 RotatingPotrait];
}
else if (selIndex == 2)
{
[view3 RotatingPotrait];
}
else if (selIndex == 3)
{
[view4 RotatingPotrait];
}
self.tabBarController.view.frame=CGRectMake(0, 0, 320, 460);
}
I have fixed problem for my project support iOS 6.0+
Steps:
1 create Subclass of UITabBarViewController and add
- (BOOL)shouldAutorotate
{
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
2 Subclass UINavigationController add
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
3 to AppDelegate add
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[[[(UINavigationController *)self.window.rootViewController viewControllers] objectAtIndex:self.tabBarController.selectedIndex] viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
4 to each UIViewController add self.tabBarCotroller.delegate = self;
and delegate method
- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController {
NSUInteger indexOfTab = [theTabBarController.viewControllers indexOfObject:viewController];
NSLog(#"Tab index = %u ", indexOfTab);
UIViewController *mVC = [[UIViewController alloc] init];
mVC.view.backgroundColor = [UIColor redColor];
mVC.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:mVC animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
}
5 to each UIViewController add orientation what you need
- (BOOL)shouldAutorotate
{
if (self.interfaceOrientation==UIInterfaceOrientationLandscapeLeft || self.interfaceOrientation==UIInterfaceOrientationLandscapeRight)
{
return NO;
} else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape; //UIInterfaceOrientationMaskPortraite
}
for me it is work
I have created example
I am showing a custom UILabel in my appdelegate class when a push notification comes. It is working fine in Portrait mode but when i rotate my device to landscape mode, label is still showing in Portrait mode. How can i fix it. I have implement rotation method. But it did not worked. Thanks in advance.
My code is :
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
CGRect frame=[[UIApplication sharedApplication] statusBarFrame];
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft
|| [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
backgroundImageView=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 480, 32)];
} else {
backgroundImageView=[[UILabel alloc] initWithFrame:CGRectMake(0, frame.size.height, 320, 44)];
NSLog(#"portrait");
}
[backgroundImageView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"alert.png"]]];
backgroundImageView.userInteractionEnabled=YES;
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(click:)];
[backgroundImageView addGestureRecognizer:tgr];
[self.window addSubview:backgroundImageView];
}![enter image description here][1]
I have done the similar kind of thing using the following code...
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self adjustUrLableViewForOrientation:toInterfaceOrientation];
}
-(void) adjustUrLableViewForOrientation:(UIInterfaceOrientation)orientation
{
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//Ur lable portrait view
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//Ur lable for landscape view
}
}
Also you can look into this changing the lable position based on the orientation.
UiWindow subviews dont rotate by themselves..
you need to check for device rotation changes like this
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:)
name:UIDeviceOrientationDidChangeNotification object:nil];
and then in the method..rotate your label manually based on current orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown );
}
Add this...Hope this helps..
Or add this:
- (BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationPortrait || UIInterfaceOrientationLandscapeLeft || UIInterfaceOrientationLandscapeRight || UIInterfaceOrientationPortraitUpsideDown ;
}
[backgroundImageView setTransform:CGAffineTransformMakeRotation(M_PI/2.0)];
Should work for this case
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 have two overlay images that I want show in camera view depending on the device orientation - one for the horizontal and one for vertical orientation (overlay_v.png and overlay_h.png). When device is rotated from portrait to vertical orientation, overlay image should change as well.
With beginGeneratingDeviceOrientationNotifications I am able only to determine the device orientation but cannot manage to change the overlay images. Any help / different approach would be very appreciated.
- (IBAction) getPhoto:(id) sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
if((UIButton *) sender == choosePhotoBtn) {
sourceCamera = false;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
} else {
sourceCamera = true;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//overlay image (cannot dynamically switch from vertical to horizontal in here)
UIImageView *anImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"overlay_v.png"]];
anImageView.frame = CGRectMake(0, 0, anImageView.image.size.width, anImageView.image.size.height);
picker.cameraOverlayView = anImageView;
//device orientation check
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didOrientation:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
[anImageView release];
}
[self presentModalViewController:picker animated:YES];
}
- (void) didOrientation: (id)object {
UIInterfaceOrientation interfaceOrientation = [[object object] orientation];
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
NSLog(#"portrait");
} else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft ){
NSLog(#"landscape");
}
}
You can't change the cameraOverlayView property once the picker is displayed. However, you can modify the view itself. Create a UIView property named overlayView. Add both images as subViews to this view and use the tag property on each image to easily grab that view again. Hide the one that shouldn't be shown for the current orientation.
- (void) didOrientation: (id)object {
UIInterfaceOrientation interfaceOrientation = [[object object] orientation];
UIImageView *pImageView = [self.overlayView viewWithTag:10];
UIImageView *lImageView = [self.overlayView viewWithTag:20];
if (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
NSLog(#"portrait");
pImageView.hidden = NO;
lImageView.hidden = YES;
} else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ){
NSLog(#"landscape");
pImageView.hidden = YES;
lImageView.hidden = NO;
}
}
I have this code, set to make the clockView appear when the phone is rotated to landscape, and then to make it go back to the mainView when it's returned to portrait. But when it does go back to portrait, the portrait view is in landscape mode. How do i fix this? This is my code.
-(void)willAnimateRotationToInterfaceOrientation(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
UIInterfaceOrientation toOrientation = self.interfaceOrientation;
if(toOrientation == UIInterfaceOrientationPortrait)
{
self.view = mainView;
}
else if(toOrientation == UIInterfaceOrientationLandscapeLeft)
{
self.view = clockView;
}
else if (toOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
self.view = mainView;
}
else if(toOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = clockView;
}
}
It is probably better to have both mainView and clockView as subviews of your view controller:
// in viewDidLoad do [self.view addSubView:mainView]; [self.view addSubView:clockView]; clockView.hidden = YES;
-(void)willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if(UIInterfaceOrientationIsPortrait(toOrientation)) {
mainView.hidden = NO;
clockView.hidden = YES;
}
else {
mainView.hidden = YES;
clockView.hidden = NO;
}
}
This way, boths views are automatically rotated in the right way and your problem should go away.