¿Puedo usar la reproducción automática para proporcionar diferentes restricciones para las orientaciones horizontal y vertical?

¿Es posible cambiar las restricciones cuando el dispositivo se gira? ¿Cómo se puede lograr esto?

Un ejemplo simple podría ser dos imágenes que, en vertical, se superponen una encima de la otra, pero en el paisaje están una al lado de la otra.

Si esto no es posible, ¿de qué otra manera podría lograr este layout?

Estoy construyendo mis puntos de vista y restricciones en el código y no uso el generador de interfaces.

Editar: utilizando el nuevo concepto de Clases de tamaño introducido en Xcode 6, puede configurar fácilmente diferentes restricciones para classs de tamaño específico en Interface Builder. La mayoría de los dispositivos (por ejemplo, todos los iPhones actuales) tienen una class de tamaño vertical compacta en modo horizontal.

Este es un concepto mucho mejor para las decisiones generales de layout que determinar la orientación del dispositivo.

Dicho esto, si realmente necesita saber la orientación, la orientación UIDevice.currentDevice().orientation es el path a seguir.


Publicación original:

Reemplace el método updateViewConstraints de UIViewController para proporcionar restricciones de layout para situaciones específicas. De esta manera, el layout siempre está configurado de la manera correcta según la situación. Asegúrese de que forman un set completo de restricciones con las creadas en el guión gráfico. Puede usar IB para configurar sus restricciones generales y marcar las que están sujetas a cambios para que se eliminen en time de ejecución.

Utilizo la siguiente implementación para presentar un set diferente de restricciones para cada orientación:

 -(void)updateViewConstraints { [super updateViewConstraints]; // constraints for portrait orientation // use a property to change a constraint's constant and/or create constraints programmatically, eg: if (!self.layoutConstraintsPortrait) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } // constraints for landscape orientation // make sure they don't conflict with and complement the existing constraints if (!self.layoutConstraintsLandscape) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation); [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait]; [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape]; } 

Ahora, todo lo que necesita hacer es disparar una actualización de restricción cada vez que cambie la situación. Anular willAnimateRotationToInterfaceOrientation:duration: para animar la actualización de restricción en el cambio de orientación:

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; [self.view setNeedsUpdateConstraints]; } 

El enfoque que estoy usando (para bien o para mal) es definir ambos sets de restricciones (retrato y paisaje) en el editor de storyboards.

Para evitar las advertencias del infierno del guión gráfico, coloco todos los sets en una prioridad de 999, solo para que no se muestre en rojo en todas partes.

Luego agrego todas las restricciones a las collections de salida:

 @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints; 

Finalmente, implemento el método viewWillLayout my ViewControllers :

 - (void) viewWillLayoutSubviews { for (NSLayoutConstraint *constraint in self.portraitConstraints) { constraint.active = (UIApplication.shanetworkingApplication.statusBarOrientation == UIDeviceOrientationPortrait); } for (NSLayoutConstraint *constraint in self.landscapeConstraints) { constraint.active = (UIApplication.shanetworkingApplication.statusBarOrientation != UIDeviceOrientationPortrait); } } 

Esto parece funcionar. Realmente deseo que pueda establecer la propiedad activa pnetworkingeterminada en el editor de storyboards.

Estoy siguiendo el mismo enfoque que el tuyo (sin files de nib o storyboards). updateViewConstraints actualizar sus restricciones en el método updateViewConstraints (comprobando la orientación del dispositivo). No hay necesidad de llamar a setNeedsUpdateConstraints en updateViewConstraints porque tan pronto como cambie la orientación del dispositivo, el último método se updateViewConstraints automáticamente.

Puede save sus restricciones, a una propiedad o variable como las versiones vertical y horizontal, luego configurarlas y eliminarlas al girar.

Lo he hecho haciendo mis restricciones en xib para la vista inicial, asignándolas a las salidas en el controller de vista. Al girar, creo las restricciones alternativas, elimine las tomas pero consérvelas, inserte las alternativas.

Invierta el process al girar hacia atrás.

Mi idea es manejar la orientación cambiando las prioridades de restricción.
Supongamos prioridades serán:

  • paisaje: 910 activo / 10 inactivo.
  • retrato: 920 activo / 20 inactivo.

Paso 1: crear un layout de paisaje (o retrato) en Storyboard con restricciones.
Paso 2: para las restricciones, que debe estar activo solo para el modo horizontal, establezca prioridad en 10.
Paso 3: Agregue restricciones para el modo vertical y establezca su prioridad en 920.

En willAnimateRotationToInterfaceOrientation agregar código:

 for (NSLayoutConstraint *constraint in myView.constraints) { if (UIInterfaceOrientationIsLandscape(UIApplication.shanetworkingApplication.statusBarOrientation)) { if (constraint.priority == 10) constraint.priority = 910; if (constraint.priority == 920) constraint.priority = 20; } else { if (constraint.priority == 20) constraint.priority = 920; if (constraint.priority == 910) constraint.priority = 10; } } 

Ventaja de este enfoque: fácil ajuste en Interface Builder. Cuando necesitamos cambiar a cualquier orientación, seleccionamos todas las restricciones por prioridad y las cambiamos simultáneamente (910-> 10, 20-> 920):

introduzca la descripción de la imagen aquí

La interfaz se rebuildá automáticamente.