pro precios precio modelos mini apple objective-c ios8 size-classes adaptive-ui

objective-c - precios - ipad pro



Clases de tamaƱo para el retrato de iPad y los modos de paisaje (6)

¿Cuán diferente será tu modo paisaje que tu modo retrato? Si es muy diferente, puede ser una buena idea crear otro controlador de vista y cargarlo cuando el dispositivo está en el paisaje

Por ejemplo

if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) //load landscape view controller here

Básicamente quiero que mis subvistas estén posicionadas de forma diferente dependiendo de la orientación del iPad (Vertical u Horizontal) usando Clases de tamaño introducidas en xcode 6. He encontrado numerosos tutoriales que explican cómo están disponibles las diferentes clases de tamaños para Iphones en retrato y paisaje en el IB pero sin embargo, parece que no hay ninguno que cubra los modos de paisaje o retrato individuales para el iPad en IB. ¿Alguien puede ayudar?


Código de Swift 3.0 para la solución @RonDiamond

class Test : UIViewController { var _willTransitionToPortrait: Bool? var _traitCollection_CompactRegular: UITraitCollection? var _traitCollection_AnyAny: UITraitCollection? func viewDidLoad() { super.viewDidLoad() self.upReferenceSizeClasses = null } func setUpReferenceSizeClasses() { var traitCollection_hCompact: UITraitCollection = UITraitCollection(horizontalSizeClass: UIUserInterfaceSizeClassCompact) var traitCollection_vRegular: UITraitCollection = UITraitCollection(verticalSizeClass: UIUserInterfaceSizeClassRegular) _traitCollection_CompactRegular = UITraitCollection(traitsFromCollections: [traitCollection_hCompact,traitCollection_vRegular]) var traitCollection_hAny: UITraitCollection = UITraitCollection(horizontalSizeClass: UIUserInterfaceSizeClassUnspecified) var traitCollection_vAny: UITraitCollection = UITraitCollection(verticalSizeClass: UIUserInterfaceSizeClassUnspecified) _traitCollection_AnyAny = UITraitCollection(traitsFromCollections: [traitCollection_hAny,traitCollection_vAny]) } func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) _willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width } func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { _willTransitionToPortrait = size.height > size.width } func overrideTraitCollectionForChildViewController(childViewController: UIViewController) -> UITraitCollection { var traitCollectionForOverride: UITraitCollection = _willTransitionToPortrait ? _traitCollection_CompactRegular : _traitCollection_AnyAny return traitCollectionForOverride }}


Como resumen de la larga respuesta de RonDiamond. Todo lo que necesita hacer es en su controlador de vista raíz.

C objetivo

- (UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController { if (CGRectGetWidth(self.view.bounds) < CGRectGetHeight(self.view.bounds)) { return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; } else { return [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]; } }

Rápido:

override func overrideTraitCollectionForChildViewController(childViewController: UIViewController) -> UITraitCollection! { if view.bounds.width < view.bounds.height { return UITraitCollection(horizontalSizeClass: .Compact) } else { return UITraitCollection(horizontalSizeClass: .Regular) } }

Luego, en storyborad usa ancho compacto para Vertical y ancho normal para Horizontal.


El iPad tiene el rasgo de tamaño "regular" para las dimensiones horizontal y vertical, sin distinción entre retrato y paisaje.

Estos rasgos de tamaño pueden UIViewController en su código de subclase UIViewController personalizado, a través del método traitCollection , por ejemplo:

- (UITraitCollection *)traitCollection { // Distinguish portrait and landscape size traits for iPad, similar to iPhone 7 Plus. UITraitCollection *superTraits = [super traitCollection]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { UITraitCollection *horizontalRegular = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]; UITraitCollection *horizontalCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection *verticalRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular]; UITraitCollection *verticalCompact = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection *regular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[horizontalRegular, verticalRegular]]; UITraitCollection *portrait = [UITraitCollection traitCollectionWithTraitsFromCollections:@[horizontalCompact, verticalRegular]]; UITraitCollection *landscape = [UITraitCollection traitCollectionWithTraitsFromCollections:@[horizontalRegular, verticalCompact]]; if ([superTraits containsTraitsInCollection:regular]) { if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) return portrait; else return landscape; } } return superTraits; }

Esto le da al iPad los mismos rasgos de tamaño que el iPhone 7 Plus. Tenga en cuenta que otros modelos de iPhone generalmente tienen el rasgo de "ancho compacto" (en lugar del ancho normal) independientemente de la orientación.

Imitar el iPhone 7 Plus de esta manera permite que ese modelo se use como un sustituto para el iPad en el Interface Builder de Xcode, que desconoce las personalizaciones en el código.

Tenga en cuenta que Split View en el iPad puede usar diferentes características de tamaño de la operación normal de pantalla completa.

Esta respuesta se basa en el enfoque adoptado en esta publicación de blog , con algunas mejoras.


La respuesta larga y útil de RonDiamond es un buen comienzo para comprender los principios; sin embargo, el código que funcionó para mí (iOS 8+) se basa en el método de anulación (UITraitCollection *)traitCollection

Por lo tanto, agregue restricciones en InterfaceBuilder con variaciones para Width - Compact, por ejemplo para la propiedad de restricción Installed. Entonces Ancho - Cualquiera será válido para paisaje, Ancho - Compacto para Retrato.

Para cambiar las restricciones en el código según el tamaño del controlador de vista actual, simplemente agregue lo siguiente en su clase UIViewController:

- (UITraitCollection *)traitCollection { UITraitCollection *verticalRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular]; if (self.view.bounds.size.width < self.view.bounds.size.height) { // wCompact, hRegular return [UITraitCollection traitCollectionWithTraitsFromCollections: @[[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact], verticalRegular]]; } else { // wRegular, hRegular return [UITraitCollection traitCollectionWithTraitsFromCollections: @[[UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular], verticalRegular]]; } }


Parece ser el intento de Apple de tratar ambas orientaciones del iPad como si fueran iguales, pero como varios de nosotros estamos descubriendo, existen motivos de diseño muy legítimos para querer variar el diseño de la interfaz de usuario para iPad Portrait frente a iPad Landscape.

Desafortunadamente, el sistema operativo actual no parece brindar soporte para esta distinción ... lo que significa que hemos vuelto a manipular las limitaciones de diseño automático en el código o soluciones similares para lograr lo que idealmente deberíamos poder obtener de forma gratuita usando la interfaz de usuario adaptable. .

No es una solución elegante.

¿No hay una forma de aprovechar la magia que Apple ya tiene incorporada en IB y UIKit para usar una clase de tamaño de nuestra elección para una orientación determinada?

~

Al pensar en el problema de manera más genérica, me di cuenta de que las "clases de tamaño" son simplemente formas de abordar diseños múltiples que se almacenan en IB, de modo que puedan invocarse según sea necesario en el tiempo de ejecución.

De hecho, una ''clase de tamaño'' es realmente solo un par de valores enum. Desde UIInterface.h:

typedef NS_ENUM(NSInteger, UIUserInterfaceSizeClass) { UIUserInterfaceSizeClassUnspecified = 0, UIUserInterfaceSizeClassCompact = 1, UIUserInterfaceSizeClassRegular = 2, } NS_ENUM_AVAILABLE_IOS(8_0);

Por lo tanto, independientemente de lo que Apple haya decidido nombrar estas diferentes variaciones, fundamentalmente, son solo un par de enteros utilizados como identificador único de géneros, para distinguir un diseño de otro, almacenado en IB.

Ahora, supongamos que creamos un diseño alternativo (usando una clase de tamaño no utilizada) en IB, digamos, para iPad Portrait ... ¿hay alguna manera de que el dispositivo use nuestra elección de clase de tamaño (diseño de UI) según sea necesario en tiempo de ejecución? ?

Después de probar varios enfoques diferentes (menos elegantes) para el problema, sospeché que podría haber una manera de anular la clase de tamaño predeterminada programáticamente. Y hay (en UIViewController.h):

// Call to modify the trait collection for child view controllers. - (void)setOverrideTraitCollection:(UITraitCollection *)collection forChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0); - (UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);

Por lo tanto, si puede empaquetar su jerarquía de controlador de vista como un controlador de vista ''hijo'' y agregarlo a un controlador de vista principal de nivel superior ... entonces puede anular condicionalmente al niño haciéndole creer que es una clase de tamaño diferente del predeterminado del sistema operativo.

Aquí hay una implementación de ejemplo que hace esto, en el controlador de vista ''padre'':

@interface RDTraitCollectionOverrideViewController : UIViewController { BOOL _willTransitionToPortrait; UITraitCollection *_traitCollection_CompactRegular; UITraitCollection *_traitCollection_AnyAny; } @end @implementation RDTraitCollectionOverrideViewController - (void)viewDidLoad { [super viewDidLoad]; [self setUpReferenceSizeClasses]; } - (void)setUpReferenceSizeClasses { UITraitCollection *traitCollection_hCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection *traitCollection_vRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular]; _traitCollection_CompactRegular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hCompact, traitCollection_vRegular]]; UITraitCollection *traitCollection_hAny = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified]; UITraitCollection *traitCollection_vAny = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassUnspecified]; _traitCollection_AnyAny = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hAny, traitCollection_vAny]]; } -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; _willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width; } - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { _willTransitionToPortrait = size.height > size.width; } -(UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController { UITraitCollection *traitCollectionForOverride = _willTransitionToPortrait ? _traitCollection_CompactRegular : _traitCollection_AnyAny; return traitCollectionForOverride; } @end

Como una demostración rápida para ver si funcionaba, agregué etiquetas personalizadas específicamente a las versiones ''Regular / Regular'' y ''Compacta / Regular'' del diseño del controlador infantil en IB:

Y esto es lo que parece correr, cuando el iPad está en ambas orientaciones:

Voila! Configuraciones de clase de tamaño personalizado en tiempo de ejecución.

Es de esperar que Apple lo haga innecesario en la próxima versión del sistema operativo. Mientras tanto, este puede ser un enfoque más elegante y escalable que interferir programáticamente con restricciones de diseño automático o realizar otras manipulaciones en el código.

~

EDITAR (6/4/15): tenga en cuenta que el código de muestra anterior es esencialmente una prueba de concepto para demostrar la técnica. Siéntase libre de adaptarse según sea necesario para su propia aplicación específica.

~

EDITAR (24/7/15): Es gratificante que la explicación anterior parezca ayudar a desmitificar el problema. Si bien no lo he probado, el código de mohamede1945 [a continuación] parece una optimización útil para fines prácticos. Siéntase libre de probarlo y dejarnos saber lo que piensa. (En aras de la integridad, dejaré el código de muestra arriba tal como está).