横向模式下的帧大小不会改变

时间:2009-06-29 13:25:22

标签: iphone cocoa-touch

我有一个UINavigationController可以旋转到横向模式,并初始化一个新的UIViewController并将其推送到堆栈上。在UIViewController's viewDidLoad我只打印self.view.frame.size

如果UINavigationController处于纵向模式,则视图控制器将打印{320,460}。但是,当导航控制器处于横向时,帧大小完全相同。 (为了澄清,在第二种情况下,UIViewController在电话已处于横向模式时初始化。)

视图的框架尺寸是否应该旋转?如果不是我怎么能找到正确的帧大小而不对数字进行硬编码?

4 个答案:

答案 0 :(得分:6)

你不能依赖横向模式的框架;你必须使用边界和中心的组合;框架是使用这些框架的组合生成的,并且当应用非标识变换时(如在横向中),它会变得有点奇怪。

答案 1 :(得分:3)

首先,您需要将视图设置为使用正确的autoresizingMask自动调整大小。 这样你的视图就会适应控制器本身的大小。

您可以使用NSLog自行检查。但是不要把它放在loadView中,这太早了。把它放在viewWillAppear。

如果使用Interface Builder设置视图的autoresizingMask,则应关闭“属性”检查器中的“模拟接口元素”。如果其中任何一个打开,则无法更改“大小”检查器中的autoresizingMask。

答案 2 :(得分:1)

这很痛苦,在iOS 4.2 for iPad中仍然如此。我解决这个问题的方法是继承与UIView相关联的UIViewController。我在界面构建器中这样做但我想也可以在代码中以某种方式执行此操作。在界面构建器中,选择UIViewController中的UIView,然后点击“检查器”窗口右上角的(i)图标。在类标识下点击弹出窗口并选择下面的UIView子类。

方法是这个UIView子类重写layoutSubviews方法,找到下一个UIViewController,确定它是否实现了reactToLayout方法(这是你必须在UIViewController子类中实现的方法这个视图的视图控制器)。如果找到的第一个UIViewController中存在reactToLayout方法,则会调用它。

视图控制器中的reactToLayout方法会执行任何需要执行的操作,因为此时视图的帧已正确设置(与ViewDidLoad不同,viewWillAppear ,甚至viewDidAppear)。我有一个方法,我可以随时调用方向或框架。这是一个痛苦,但我存储了最后一帧,并在视图控制器的内部变量中布置了最后一个方向。新方向或框架更改方法的内部布局将这些与视图的当前框架和请求或当前方向进行比较,以便不会不必要地反复布局内容。

以下是代码:

UILayoutSubviewsView.h

#import <UIKit/UIKit.h>

@interface UILayoutSubviewsView : UIView {
}

@end

UILayoutSubviewsView.m

#import "UILayoutSubviewsView.h"

// Create this to avoid a warning that this method does not exist for UIViewControllers
// this is OK since we check to see that it does exist before invoking it
@interface UIViewController(UndocumentedMethodForUIViewController)
-(void) reactToLayout;
@end

@implementation UILayoutSubviewsView

// Pass this up to our view controller if it supports the reactToLayout method
// (this is the whole reason for the class)
-(void) layoutSubviews {
  [super layoutSubviews];

  // Look for the first next responder that is a UIViewController
  UIViewController *ourViewController = nil;
  id myNextResponder = [self nextResponder];
  while (myNextResponder != nil && ourViewController == nil) {
    if ([myNextResponder isKindOfClass:[UIViewController class]]) {
      ourViewController = myNextResponder;
    }
    else {
      myNextResponder = [myNextResponder nextResponder];
    }    
  }

  // If we got a view controller, then see if it supports the reactToLayout method
  if (ourViewController != nil) {
    if ([ourViewController respondsToSelector:@selector(reactToLayout)]) {

      // Invoke the view controller's reactToLayout method
      [ourViewController reactToLayout];

    }
  }

}

@end

YourViewController.h

#import <UIKit/UIKit.h>

@interface YourViewController : UIViewController {
  CGRect lastLayedOutFrame;
  UIInterfaceOrientation lastLayedOutOrientation;
}

#pragma mark -
#pragma mark Instance Methods
-(id) init;
-(void) reactToLayout;

@end

YourViewController.m

#import "YourViewController.m"

#pragma mark Private Interface Category
@interface YourViewController()
-(void) setViewForCurrentFrameAndRequestedOrientation:(UIInterfaceOrientation) interfaceOrientation;
@end

@implementation YourPadViewController

-(id) init {

  // First our super then set ourselves up
  if (self = [super initWithNibName:@"YourViewController" bundle:nil]) {

    // Initialize some basic stuff
    lastLayedOutFrame = CGRectZero;
    lastLayedOutOrientation = UIDeviceOrientationUnknown;

  }

  return self;
}

-(void) viewWillAppear:(BOOL) animated {
  [super viewWillAppear:animated];

  // Make sure we're showing the right stuff in the right place
  [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown];

}

-(void) viewDidAppear:(BOOL) animated {
  [super viewDidAppear:animated];

  // Make sure we're showing the right stuff in the right place
  [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown];

}

-(void) reactToLayout {

  // Make sure we're showing the right stuff in the right place
  [self setViewForCurrentFrameAndRequestedOrientation:UIDeviceOrientationUnknown];

}

#pragma mark -
#pragma mark Rotation Support
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
  return YES;
}

// This is called right before the actual rotation
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval) duration {
  [super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration];

  // Make sure we're showing the right stuff in the right place
  [self setViewForCurrentFrameAndRequestedOrientation:interfaceOrientation];

}

// Make the necessary adjustments for the different view orientations
-(void) setViewForCurrentFrameAndRequestedOrientation:(UIInterfaceOrientation) interfaceOrientation {

  // Set up the requested orientation (need this to handle the Unknown case)
  UIInterfaceOrientation requestedOrientation;
  if (interfaceOrientation != UIDeviceOrientationUnknown) {
    requestedOrientation = interfaceOrientation;
  }
  else {
    requestedOrientation = [[UIDevice currentDevice] orientation];
  }

  // See if we have anything to do
  if (!(CGRectEqualToRect(self.view.frame, lastLayedOutFrame) && lastLayedOutOrientation == requestedOrientation)) {

    // Do whatever needs to be done

    // Record our last layed out frame and orientation
    lastLayedOutFrame = self.view.frame;
    lastLayedOutOrientation = requestedOrientation;

  }

}

答案 3 :(得分:0)

大家好 我认为有一个简单的解决方案可以帮我完成工作 你可以使用currentSize而不是self.view.frame.size

在yourClass.h中

@interface yourClass : UIViewController {
    CGSize currentSize;
}
@property (nonatomic, readwrite)CGSize currentSize;
@end

在yourClass.m

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration                                        
{   
    if (toInterfaceOrientation != self.interfaceOrientation) {
        CGSize newSize;
        // 20 is the status bar height
        newSize.width = self.view.bounds.size.height + 20;
        newSize.height = self.view.bounds.size.width - 20;
        currentSize = newSize;
        //any other necessary code
    }
}