Search code examples
iphonewindowsubviewrotation

Window subview not rotating after orientation of the device changes


I'm creating an UIView with a label inside AppDelegate and displaying it like this:

    [window addSubview:self.roundedCornerView];

Problem is when I rotate the device the view with label don't rotate at all. The text in the label is in wrong orientation as well. Window in my application got another subview which is the UIViewControllers subview and it is rotating fine.

Do I need to create another UIViewController in my AppDelegate and attach created view to it, then subclassing it and allowing for interface orientation in order to get roundedCornerView to rotate?

UPDATE Ok I've tried to do this by creating new ViewController and sublcassing it here is code in my AppDelegate:

    ActivityIndicatorWithLabelViewController *aiWithLabel = [[[ActivityIndicatorWithLabelViewController alloc] init] autorelease];
aiWithLabel.textOfTheLabel = text;

[window addSubview:aiWithLabel.view];

The ActivityIndicatorWithLabelViewController class is visible here:

//
//  ActivityIndicatorWithLabelViewController.m
//  LOFT
//
//  Created by Marcin Zyga on 15.11.2011.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "ActivityIndicatorWithLabelViewController.h"

@implementation ActivityIndicatorWithLabelViewController
@synthesize roundedCornerView;
@synthesize textActivityIndicatorLabel;
@synthesize textOfTheLabel;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];

    UIActivityIndicatorView *mainApplicationActivityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    mainApplicationActivityIndicatorView.frame = CGRectMake(80, 80, 40, 40);
    mainApplicationActivityIndicatorView.hidesWhenStopped = YES;


    //self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(280, 400, 200, 200)] autorelease];
    self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)] autorelease];
    roundedCornerView.backgroundColor = [UIColor blackColor];
    roundedCornerView.alpha = 0.9f;
    roundedCornerView.layer.cornerRadius = 12.0;
    [roundedCornerView addSubview:mainApplicationActivityIndicatorView];


    [mainApplicationActivityIndicatorView startAnimating];
    //  self.roundedCornerView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
    //self.roundedCornerView.autoresizesSubviews = YES;



    self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150, 200, 50)];
    self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
    self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
    self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
    self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
    self.textActivityIndicatorLabel.text = @"";
    //  self.textActivityIndicatorLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth; 
    [self.roundedCornerView addSubview:textActivityIndicatorLabel]; 
    self.textActivityIndicatorLabel.text = textOfTheLabel;

    self.view.frame = CGRectMake(280, 400, 200, 200);
    [self.view addSubview:self.roundedCornerView];
    //self.view = self.roundedCornerView;

}


- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
        [self.textActivityIndicatorLabel removeFromSuperview];
        [self.textActivityIndicatorLabel release];

        self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
        self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
        self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
        self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
        self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
        self.textActivityIndicatorLabel.text = @"Landscape";
        [self.roundedCornerView addSubview:textActivityIndicatorLabel];         

        NSLog(@"LANDSCAPE");
    }
    NSLog(@"ENTERING SUPPORTED ORIENTATION!");
    return YES;
}

@end

As you see there is some debug code in here. When I'm rotating the device from potrait to landscape I get ENTERING SUPPORTE ORIENTATION! as well as LADNSCAPE NSLog. Removing label is working fine, but when I'm adding new one it is still presented (the text) in wrong orientation. What I am doing wrong?


Solution

  • Solution is follow below steps :

    • In subView's .m file add code on top of interface of you view:

      typedef NS_OPTIONS(NSUInteger, AGInterfaceOrientationMask) {
        AGInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
        AGInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
        AGInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
        AGInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
        AGInterfaceOrientationMaskLandscape = (AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
        AGInterfaceOrientationMaskAll = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight | AGInterfaceOrientationMaskPortraitUpsideDown),
        AGInterfaceOrientationMaskAllButUpsideDown = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
      }
      
    • In subView's .m file add code

      #pragma mark - Orientation
      
      - (void)statusBarFrameOrOrientationChanged:(NSNotification *)notification
      {
        /*
        This notification is most likely triggered inside an animation block,
        therefore no animation is needed to perform this nice transition.
        */
        [self rotateAccordingToStatusBarOrientationAndSupportedOrientations];
      }
      
      - (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations
      {
          UIInterfaceOrientation orientation = [self desiredOrientation];
          CGFloat angle = [self UIInterfaceOrientationAngleOfOrientation:orientation];
          CGFloat statusBarHeight = [[self class] getStatusBarHeight];
          UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
      
          CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
          CGRect frame = [[self class] rectInWindowBounds:self.view.window.bounds statusBarOrientation:statusBarOrientation statusBarHeight:statusBarHeight];
      
          [self setIfNotEqualTransform:transform frame:frame];
      
          CGRect rect = btnClose.frame;
          rect.origin.x = (subView.frame.origin.x+subView.frame.size.width)-(rect.size.width/2);
          rect.origin.y = subView.frame.origin.y-(rect.size.height/2);
          btnClose.frame = rect;
      }
      
      - (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame
      {
          if(!CGAffineTransformEqualToTransform(self.view.transform, transform))
          {
              self.view.transform = transform;
          }
          if(!CGRectEqualToRect(self.view.frame, frame))
          {
              self.view.frame = frame;
          }
      }
      
      + (CGFloat)getStatusBarHeight
      {
          UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
          if(UIInterfaceOrientationIsLandscape(orientation))
          {
              return [UIApplication sharedApplication].statusBarFrame.size.width;
          }
          else
          {
              return [UIApplication sharedApplication].statusBarFrame.size.height;
          }
      }
      
      static BOOL IS_BELOW_IOS_7()
      {
          static BOOL answer;
          static dispatch_once_t onceToken;
          dispatch_once(&onceToken, ^{
              answer = [[[UIDevice currentDevice] systemVersion] floatValue] < 7.0;
          });
          return answer;
      }
      
      + (CGRect)rectInWindowBounds:(CGRect)windowBounds statusBarOrientation:(UIInterfaceOrientation)statusBarOrientation statusBarHeight:(CGFloat)statusBarHeight
      {
          CGRect frame = windowBounds;
      
          if(IS_BELOW_IOS_7())
          {
              frame.origin.x += statusBarOrientation == UIInterfaceOrientationLandscapeLeft ? statusBarHeight : 0;
              frame.origin.y += statusBarOrientation == UIInterfaceOrientationPortrait ? statusBarHeight : 0;
              frame.size.width -= UIInterfaceOrientationIsLandscape(statusBarOrientation) ? statusBarHeight : 0;
              frame.size.height -= UIInterfaceOrientationIsPortrait(statusBarOrientation) ? statusBarHeight : 0;
          }
          return frame;
      }
      
      - (UIInterfaceOrientation)desiredOrientation
      {
          UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
          AGInterfaceOrientationMask statusBarOrientationAsMask = [self AGInterfaceOrientationMaskFromOrientation:statusBarOrientation];
          if(self.supportedInterfaceOrientations & statusBarOrientationAsMask)
          {
              return statusBarOrientation;
          }
          else
          {
              if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskPortrait)
              {
                  return UIInterfaceOrientationPortrait;
              }
              else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeLeft)
              {
                  return UIInterfaceOrientationLandscapeLeft;
              }
              else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeRight)
              {
                  return UIInterfaceOrientationLandscapeRight;
              }
              else
              {
                  return UIInterfaceOrientationPortraitUpsideDown;
              }
          }
      }
      
      -(CGFloat)UIInterfaceOrientationAngleOfOrientation:(UIInterfaceOrientation)orientation
      {
          CGFloat angle;
      
          switch (orientation)
          {
              case UIInterfaceOrientationPortraitUpsideDown:
                  angle = M_PI;
                  break;
              case UIInterfaceOrientationLandscapeLeft:
                  angle = -M_PI_2;
                  break;
              case UIInterfaceOrientationLandscapeRight:
                  angle = M_PI_2;
                  break;
              default:
                  angle = 0.0;
                  break;
          }
      
          return angle;
      }
      
      -(AGInterfaceOrientationMask)AGInterfaceOrientationMaskFromOrientation:(UIInterfaceOrientation)orientation
      {
          return 1 << orientation;
      }
      
      //If dealloc is a duplicate method then remove this dealloc method and add the unregisterFromNotifications method in dealloc.
      - (void)dealloc {
          [self unregisterFromNotifications];
      }
      
      -(void)unregisterFromNotifications
      {
          //for orientation
          [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
          [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
      }
      
    • Also In subView's .h file add this line.

      - (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations;
      

    Now time to use above added code for orientation change in subview.

    • While adding subview in window or self.view like this :

      [objAppDelegate.window addSubview:objViewController.view];
      
      //added this method to rotate subview according to orientation when added
      [objViewController rotateAccordingToStatusBarOrientationAndSupportedOrientations];
      

    Reference taken from AGWindowView