2009-06-29 16 views
8

Tengo un UINavigationController que puede girar al modo horizontal y que inicializa un nuevo UIViewController y lo empuja en la pila. En el UIViewController'sviewDidLoad acabo de imprimir el self.view.frame.size.el tamaño del marco no cambia en el modo horizontal

Si el UINavigationController está en modo vertical, el controlador de vista imprimirá {320, 460}. Sin embargo, cuando el Controlador de navegación está en Paisaje, el tamaño del cuadro es exactamente el mismo. (Para aclarar, en el segundo caso, el UIViewController se inicializa cuando el teléfono ya está en modo apaisado.)

¿No se debe rotar el tamaño de marco de la vista? Y si no, ¿cómo puedo encontrar el tamaño de fotograma correcto sin codificar los números?

Respuesta

6

No puede confiar en el marco en modo horizontal; tienes que usar una combinación de límites y centro; frame se genera usando una combinación de esos, y cuando hay una transformación no identificada aplicada (como en el paisaje), se pone un poco raro.

+0

Puedes por favor elaborar? Los límites también son idénticos {320, 460} en ambos casos y el centro tampoco cambia. – user130444

+0

Si está preguntando por qué no se cambia el tamaño del cuadro, ¿los resortes y puntales están configurados correctamente? Eso es lo primero que debes verificar. –

+0

Sí y mi vista cambia el tamaño correctamente cuando se gira. El único problema es cuando se crea mientras está en Paisaje. – user130444

3

primero tiene que configurar su vista para cambiar el tamaño automáticamente con una apropiada autoresizingMask. con esto su vista se adaptará al tamaño del controlador.

puede verificarlo usted mismo con un NSLog. Pero no lo pongas en loadView, esto es demasiado temprano. Pon esto a la vista WillAppear.

Si configura el encoder automático de su vista con Interface Builder, debe desactivar los Elementos de interfaz simulada en el inspector de atributos. Si alguno de estos está activado, no puede cambiar el autoresizingMask en el inspector de tamaño.

+1

Gracias por la sugerencia sobre viewWillAppear. – David

+0

+1 a Denis y David. Esta debería ser la respuesta aceptada para este problema de tamaño con controladores creados en modo horizontal. –

1

Esto es un dolor y sigue siendo cierto en iOS 4.2 para iPads. La forma en que resolvió esto es subclase el UIView asociado con el UIViewController. Hice esto en el constructor de interfaz, pero supongo que uno también podría hacer esto en código de alguna manera. En el constructor de interfaces, seleccione UIView en el UIViewController y luego presione el ícono (i) en la esquina superior derecha de la ventana del Inspector. Debajo de la identidad de clase, presione la ventana emergente y elija la subclase UIView a continuación.

El enfoque es que esta subclase UIView reemplaza el método layoutSubviews, encuentra el siguiente UIViewController, determina si se implementa un método reactToLayout (que es un método que hay que aplicar en la subclase UIViewController para el controlador de vista de este punto de vista) . Si el método reactToLayout existe en el primer UIViewController encontrado, se invoca.

El método reactToLayout en el controlador de vista y luego hace lo que uno tiene que hacer lo que será capaz de hacer con éxito desde el marco de la vista está configurado correctamente en ese momento (al contrario que en ViewDidLoad, viewWillAppear, o incluso viewDidAppear). Tengo un método que llamo cada vez que cambia la orientación o el marco. Es un problema, pero guardo el último cuadro presentado y la última orientación presentada en las variables internas del controlador de vista. El diseño interno de la nueva orientación o el método de cambio de marco los compara con el marco actual de la vista y la orientación solicitada o actual para que no se distribuya innecesariamente una y otra vez.

Aquí está el código:

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

Hola cada uno Creo que hay una solución simple que hacer el trabajo para mí puede utilizar currentSize en lugar de self.view.frame.size

en yo urClass.h

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

en 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 
    } 
} 
+0

buena solución;) pero self.interfaceOrientation me da mal acceso ..?! –

Cuestiones relacionadas