размер кадра не меняется в ландшафтном режиме - PullRequest
8 голосов
/ 29 июня 2009

У меня есть UINavigationController, который может поворачиваться в ландшафтный режим и инициализировать новый UIViewController и помещать его в стек. На UIViewController's viewDidLoad я просто печатаю self.view.frame.size.

Если UINavigationController находится в портретном режиме, контроллер вида напечатает {320, 460}. Однако, когда контроллер навигации находится в альбомной ориентации, размер кадра точно такой же. (Для пояснения, во втором случае UIViewController инициализируется, когда телефон уже находится в альбомном режиме.)

Не следует ли поворачивать размер кадра вида? И если нет, то как я могу найти правильный размер кадра без жесткого кодирования чисел?

Ответы [ 4 ]

6 голосов
/ 29 июня 2009

Вы не можете полагаться на кадр в ландшафтном режиме; Вы должны использовать комбинацию границ и центра; кадр генерируется с использованием их комбинации, и когда применяется преобразование без идентификации (как в ландшафте), оно становится немного странным.

3 голосов
/ 01 ноября 2009

сначала вам нужно настроить вид для автоматического изменения размера с помощью правильной autoresizingMask. с этим ваше представление будет адаптироваться к размеру самого контроллера.

Вы можете проверить это самостоятельно с помощью NSLog. Но не помещайте это в loadView, это слишком рано. Поместите это в viewWillAppear.

Если вы установили autoresizingMask вашего представления в Интерфейсном Разработчике, вы должны отключить Имитированные Элементы Интерфейса в Инспекторе Атрибутов. Если какой-либо из них включен, вы не можете изменить autoresizingMask в Инспекторе размера.

1 голос
/ 08 января 2011

Это боль, и это все еще верно в iOS 4.2 для iPad. Я решил, что это подкласс UIView, связанный с UIViewController. Я сделал это в конструкторе интерфейсов, но я полагаю, что кто-то мог также сделать это в коде. В конструкторе интерфейса выберите UIView в UIViewController, затем нажмите значок (i) в верхнем правом углу окна инспектора. Под идентификатором класса нажмите всплывающее окно и выберите подкласс UIView ниже.

Подход заключается в том, что этот подкласс UIView переопределяет метод layoutSubviews, находит следующий UIViewController, определяет, реализует ли он методactToLayout (который необходимо реализовать в подклассе UIViewController для контроллера представления этот вид). Если методactToLayout существует в первом найденном UIViewController, он вызывается.

Затем методactToLayout в контроллере представления выполняет все, что ему нужно, что он сможет успешно выполнить, поскольку к этому времени кадр представления настроен правильно (в отличие от ViewDidLoad, viewWillAppear или даже *). 1013 *). У меня есть метод, который я вызываю каждый раз, когда меняется ориентация или рамка. Это неприятно, но я сохраняю последний развернутый кадр и последнюю ориентацию во внутренних переменных контроллера представления. Внутренний макет для новой ориентации или метода смены кадров сравнивает их с текущим кадром и запрошенной или текущей ориентацией представления, чтобы он не создавал ненужные макеты снова и снова.

Вот код:

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;

  }

}
0 голосов
/ 05 апреля 2011

Привет всем Я думаю, что есть простое решение, которое делает работу за меня вы можете использовать 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...