2010-04-19 18 views
21

Tengo problemas para obtener los límites correctos para mi aplicación iPad al iniciarla en modo horizontal. Tengo las claves correctas establecidas en mi archivo Info.plist y mis controladores de vista se inician correctamente en landscape (y portrait, natch).UIScreen applicationFrame devuelve un rectángulo incorrecto en el inicio de la aplicación horizontal (iPhone/iPad)

En mi método applicationDidFinishLaunching: estoy llamando a un selector después de un retraso de 3 segundos, y ese método hace una llamada a [[UIScreen mainScreen] applicationFrame], pero me está devolviendo un retrato (es decir, alto> ancho).

¿Alguien sabe cómo solucionar esto? A mí me huele a error (si es así, archivaré un radar), pero si se trata de un comportamiento intencionado, ¿dónde está documentado?

+16

¿Puedo simplemente decir "sin sentido" a partir de ahora? – jbrennan

Respuesta

6

Cuando sostenga el iPad en orientación horizontal e inicie una aplicación, el controlador de vista inicialmente ve límites para una vista de retrato (aunque los informes de orientación son apaisados). El controlador de vista recibirá un mensaje para rotar a orientación horizontal antes de que aparezca.

+0

Entonces, después de que el mensaje se envía al controlador de vista para rotar, ¿el sistema de coordenadas reflejará la nueva orientación? Por ejemplo, después de enviar el mensaje, ¿ancho> alto? –

5

Esto es como diseñado. Debería consultar el tamaño de su supervista y ajustarla según sea necesario.

+0

¿Podría explicar por qué esto está diseñado de esta manera (o al menos especular). Me parece ilógico dar límites incorrectos para la pantalla si se ha girado. La 'supervista' en cuestión es la ventana de mi aplicación (y he intentado usar su marco también para obtener los mismos resultados). – jbrennan

+0

La razón es que las ventanas se pueden rotar independientemente de la pantalla. Ejemplo: cuando una aplicación de retrato lanza un video de YouTube, la ventana principal permanece vertical, pero una ventana horizontal se anima sobre la parte superior. Durante la animación, ¿se debe considerar el dispositivo como retrato o paisaje? (La orientación del acelerómetro es independiente de la orientación de la ventana, está separada de la orientación de la barra de estado) – rpetrich

+0

Me he dado cuenta de esto también, es realmente extraño. Gracias por el aviso. – Justin

35

Nunca confío en [[UIScreen mainScreen] applicationFrame], especialmente durante el lanzamiento de la aplicación.

Al crear vistas en código, use la supervista para establecer su marco.

Si está utilizando xibs con "elementos de interfaz simulados" tendrán el tamaño correcto y todo funcionará muy bien.

aplicaciones basadas UINavigationController

En el caso de una aplicación basada en UINavigationController, agarran el bastidor directamente de self.navigationController.view, no trate de usar [self loadView] y self.view.superview. UINavigationController utiliza subvistas "ocultas" para hacer su trabajo, por lo que la supervista directa no funcionará.

UINavigationController es especial porque durante el inicio de la aplicación, el controlador de navegación cambia el tamaño de sus vistas después de que se llama al loadView. Cuando se inician las patadas, se termina con un pequeño margen en la parte inferior de la pantalla.

Por qué no UIScreen

[[UIScreen mainScreen] applicationFrame] no funciona de forma fiable (especialmente durante el lanzamiento de aplicaciones en el paisaje). Mi experiencia es que la propiedad interfaceOrientation del viewcontroller no coincidirá con la orientación applicationFrame.

+0

¡Esto es muy importante! Gracias – coco

+0

¡Esto es muy útil! ¡Si lo hubiera encontrado antes, habría ahorrado mucho tiempo! ¡Gracias! – coder284

6

Ésta es la manera tengo la CGRect correcta cuando el controlador de vista es en el paisaje:

CGRect landscapeBounds; 
if (self.view.frame.size.width < self.view.frame.size.height) 
    landscapeBounds = CGRectMake(self.view.frame.origin.y, self.view.frame.origin.x, self.view.frame.size.height, self.view.frame.size.width); 
else 
    landscapeBounds = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); 
0

entré en mismo problema al despedir a la vista con dismissViewControllerAnimated en Córdoba plugin. he modificado el código para el método singingAtom viewWillAppear en MainViewController, que consiguió cambiar el tamaño después de despedir vista modal:

- (void)viewWillAppear:(BOOL)animated 
    { 
    CGRect appFrame = [[UIScreen mainScreen] applicationFrame]; 
    UIDeviceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 
    if (UIDeviceOrientationLandscapeLeft == orientation || 
     UIDeviceOrientationLandscapeRight == orientation) 
      { 
      if (appFrame.size.width < appFrame.size.height) 
       { 
       appFrame = CGRectMake(appFrame.origin.y, appFrame.origin.x, appFrame.size.height, appFrame.size.width); 
       } 
     } 
    self.view.frame = appFrame; 
    [super viewWillAppear:animated]; 
} 
14
CGRect bounds = [[UIScreen mainScreen] bounds]; // portrait bounds 
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { 
    bounds.size = CGSizeMake(bounds.size.height, bounds.size.width); 
} 
1

Por lo tanto, añadir una imagen de lanzamiento y darle la -568h sufijo, de acuerdo a las guías de Apple.

No entiendo por qué alguien con una mente sana haría que la configuración de un sistema dependa de un gráfico; pero acabo de probar y funcionó.

Here is the spot that taught me after a quick search No vi esta respuesta arriba, pensé que sería útil para alguien.

S

2

[[UIScreen mainScreen] applicationFrame] siempre devolverá el rectángulo vertical aunque la aplicación es en modo horizontal. Esto está relacionado con el hecho de que UIWindownunca realmente gira, sino que simplemente cambia la transformación de rootViewController.view en su lugar.

Para asegurarse, puede imprimir el objeto vista raíces en modos vertical y horizontal, y verá algo como esto:

Retrato:

<UIView: 0x96290e0; frame = (0 20; 768 1004); ... 

paisaje:

<UIView: 0x96290e0; frame = (0 20; 768 1004); transform = [0, 1, -1, 0, 0, 0]; ... 
Cuestiones relacionadas