manejo de orientación de iphone / ipad

Esta es una pregunta más general para que la gente me brinde orientación, básicamente estoy aprendiendo el desarrollo de iPad / iPhone y finalmente me he topado con la pregunta de soporte de orientación múltiple.

He buscado una buena cantidad de doco, y mi libro “Beginning iPhone 3 Development” tiene un buen capítulo sobre él.

Pero mi pregunta es la siguiente: si tuviera que cambiar programáticamente mis controles (o incluso usar diferentes vistas para cada orientación) ¿cómo diablos las personas pueden mantener su código base? Me imagino tantos problemas con el código de spaghetti / miles de controles “si” por todas partes, que me volvería loco hacer un pequeño cambio en el arreglo de UI.

¿Alguien tiene experiencia manejando este problema? ¿Cuál es una buena forma de controlarlo?

Muchas gracias Mark

Lo hago con dos métodos simples en mi controlador de vista:

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [self adjustViewsForOrientation:toInterfaceOrientation]; } - (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation { if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) { titleImageView.center = CGPointMake(235.0f, 42.0f); subtitleImageView.center = CGPointMake(355.0f, 70.0f); ... } else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { titleImageView.center = CGPointMake(160.0f, 52.0f); subtitleImageView.center = CGPointMake(275.0f, 80.0f); ... } } 

Para mantener esto limpio, puede compartimentar fácilmente los ajustes de vista / recarga / etc. con métodos llamados desde el único condicional if-else .

Realmente depende de lo que estás diseñando.

Si observa la aplicación Configuración de Apple, puede ver que usan vistas de tabla para el diseño, con celdas personalizadas para la mayoría de las filas. Con eso, puedes permitir que una interfaz simple gire a un precio muy económico simplemente rellenando el ancho de las celdas. Esto incluso se aplica a cosas como Correo, donde hay celdas de texto de edición en cada fila. Y las tablas pueden ser transparentes, con solo botones o tags visibles, para que no se vean como tablas.

Puedes obtener una gran cantidad de millas de la autenticación automática de cada UIView. Si tiene uno o más elementos que pueden tener una altura flexible, generalmente puede obtener un diseño de interfaz que se ve bien en cualquier orientación. Dependiendo de cómo se ve, a veces puedes simplemente fijar todo en la parte superior.

En casos excepcionales, si todos los elementos de la interfaz encajan en un cuadrado, puede rotarlos en su lugar.

Hay dos momentos en los que debe manejar explícitamente los cambios de orientación. Uno de ellos es cuando una vista se mueve de lado a lado por debajo de otro en rotación. La otra es cuando tiene diferentes imágenes para cada orientación, por ejemplo, si siempre quiere tener el ancho completo.

A veces hay formas de evitar ambos. Puede usar imágenes elásticas o limitarse a una vista por línea. O puede bloquear la orientación de ciertas vistas.

Si debe cambiar el diseño de las vistas, existe un método explícito de layoutSubviews. Deberías tratar de manejar todo tu diseño condicional en este único método. Solo se invoca cuando cambian los límites de la vista, por ejemplo, en la rotación o si ha dejado espacio para el teclado. Cree una vista personalizada para cada jerarquía de vistas que deba responder a la rotación y diseñe las subvistas desde allí.

El iPhone SDK se basa en tener una architecture MVC, por lo que, en teoría, si mantienes toda tu lógica (modelo) separada de tu UI (vista), entonces solo tendrás que preocuparte por la UI en un solo lugar: tus controladores de vista. Para ellos, podría tener un controlador de vista separado para cada orientación, cada uno de los cuales se cargaría con un if / else para elegir qué controlador de vista cargar.

La misma idea se aplica al soporte para iPhone / iPad, donde puede cargar otro controlador de visualización que puede manejar pantallas más grandes.

No puedo responder por este código, y honestamente, lo anterior girará a la orientación de la interfaz funciona muy bien. Aquí hay otra versión con FBDialog.m de Facebook para iphone / ipad. (aunque, creo que esto fue para una vista web)

aquí está la esencia

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; - (void)deviceOrientationDidChange:(void*)object { UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if ([self shouldRotateToOrientation:orientation]) { CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:duration]; [self sizeToFitOrientation:YES]; [UIView commitAnimations]; } } -(CGAffineTransform)transformForOrientation { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (orientation == UIInterfaceOrientationLandscapeLeft) { return CGAffineTransformMakeRotation(M_PI*1.5); } else if (orientation == UIInterfaceOrientationLandscapeRight) { return CGAffineTransformMakeRotation(M_PI/2); } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { return CGAffineTransformMakeRotation(-M_PI); } else { return CGAffineTransformIdentity; } } - (void)sizeToFitOrientation:(BOOL)transform { if (transform) { self.transform = CGAffineTransformIdentity; } CGRect frame = [UIScreen mainScreen].applicationFrame; CGPoint center = CGPointMake( frame.origin.x + ceil(frame.size.width/2), frame.origin.y + ceil(frame.size.height/2)); CGFloat scale_factor = 1.0f; if (FBIsDeviceIPad()) { // On the iPad the dialog's dimensions should only be 60% of the screen's scale_factor = 0.6f; } CGFloat width = floor(scale_factor * frame.size.width) - kPadding * 2; CGFloat height = floor(scale_factor * frame.size.height) - kPadding * 2; _orientation = [UIApplication sharedApplication].statusBarOrientation; if (UIInterfaceOrientationIsLandscape(_orientation)) { self.frame = CGRectMake(kPadding, kPadding, height, width); } else { self.frame = CGRectMake(kPadding, kPadding, width, height); } self.center = center; if (transform) { self.transform = [self transformForOrientation]; } } 

En su pregunta, usted escribió:

Me imagino tantos problemas con el código de spaghetti / miles de controles “si” por todas partes, que me volvería loco hacer un pequeño cambio en el arreglo de UI.

Una forma de evitar esto es crear una jerarquía de vista que divida desde el principio el manejo de los cambios específicos de iPhone / iPad. Solo debe establecer qué vista se carga inicialmente para cada dispositivo. Luego crea un controlador de vista como lo hace normalmente, pero también subclase el controlador de vista que ha creado. Una subclase para cada dispositivo. Ahí es donde puedes poner el código específico del dispositivo, como el manejo de la orientación. Me gusta esto:

 MyViewController.h // Code that is used on both devices MyViewController_iPhone.h // iPhone specific code, like orientation handling MyViewController_iPad.h // iPad specific code, like orientation handling 

Si está interesado en este enfoque, le sugiero que lea este artículo . Lo explica de una manera muy agradable.

Una de las cosas que menciona el artículo es esta:

– comienzo de cita–

La belleza de este patrón es que no tenemos que ensuciar nuestro código con basura que se ve así:

 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { // The device is an iPad running iPhone 3.2 or later. // set up the iPad-specific view } else { // The device is an iPhone or iPod touch. // set up the iPhone/iPod Touch view } 

—fin de la cita–

Espero que eso ayude. ¡Buena suerte!