【问题标题】:Window subview not rotating after orientation of the device changes设备方向更改后窗口子视图不旋转
【发布时间】:2011-11-15 16:38:40
【问题描述】:

我正在 AppDelegate 中创建一个带有标签的 UIView,并像这样显示它:

    [window addSubview:self.roundedCornerView];

问题是当我旋转设备时,带有标签的视图根本不旋转。标签中的文本也方向错误。我的应用程序中的窗口有另一个子视图,它是 UIViewControllers 子视图,它可以正常旋转。

我是否需要在我的 AppDelegate 中创建另一个 UIViewController 并将创建的视图附加到它,然后对其进行子类化并允许界面方向以使 roundedCornerView 旋转?

更新 好的,我尝试通过创建新的 ViewController 并将其子类化来实现这一点,这是我的 AppDelegate 中的代码:

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

[window addSubview:aiWithLabel.view];

ActivityIndi​​catorWithLabelViewController 类在这里可见:

//
//  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

如您所见,这里有一些调试代码。当我将设备从纵向旋转到横向时,我得到了 ENTERING SUPPORTE ORIENTATION!以及 LADNSCAPE NSLog。删除标签工作正常,但是当我添加新标签时,它仍然以错误的方向显示(文本)。我做错了什么?

【问题讨论】:

    标签: iphone window subview rotation


    【解决方案1】:

    UIWindow 应该只有一个定义根 UIViewController 的子视图。我相信 UIWindow 只会将旋转事件转发到它的第一个子视图。

    创建一个容器 UIView 并将您的子视图移动到其中。

    【讨论】:

    • 恐怕这个解决方案也行不通。这是我的新代码,它与我的帖子中的行为相同: UIView *containerView = [[UIView alloc] initWithFrame:[navController.view frame]]; [containerView addSubview:navController.view]; ActivityIndi​​catorWithLabelViewController *aiWithLabel = [[[ActivityIndi​​catorWithLabelViewController alloc] init] autorelease]; aiWithLabel.textOfTheLabel = @"测试"; [containerView addSubview:aiWithLabel.view]; [窗口 addSubview:containerView];
    • 请上传您的整个项目目录。
    • 我不能。但是我已经设法通过执行以下操作来解决此问题: [[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0] addSubview:self.view];其中 self.view 是来自 ActivityIndi​​catorWithLabelViewController 的视图
    • 听起来你已经在某处的窗口中添加了一个子视图。这可以在 MainWindow.xib 中完成。
    【解决方案2】:

    解决方案遵循以下步骤

    • 在 subView 的 .m 文件中,在您的视图界面顶部添加代码:

      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),
      }
      
    • 在 subView 的 .m 文件中添加代码

      #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];
      }
      
    • 同样在 subView 的 .h 文件中添加这一行。

      - (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations;
      

    现在是时候使用上面添加的代码来改变子视图的方向了。

    • 在 window 或 self.view 中添加子视图时:

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

    参考取自AGWindowView

    【讨论】:

      【解决方案3】:

      窗口子视图不会自行旋转,它们通常在视图控制器的帮助下旋转。

      您可以将要旋转的视图添加到视图控制器,然后将其添加到窗口,或者您可以注册设备方向更改通知并自行旋转它们。

      【讨论】:

      • 我尝试按照您提出的方式执行此操作,但仍然是同样的问题。我将更新我的帖子以发布完整的代码。
      猜你喜欢
      • 2020-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多