¿Puedo usar el diseño automático para proporcionar diferentes restricciones para las orientaciones de paisaje y retrato?

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

Un ejemplo simple podría ser dos imágenes que, en vertical, están astackdas 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 forma podría lograr este diseño?

Estoy construyendo mis puntos de vista y restricciones en el código y no usando el constructor de interfaz.

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

Este es un concepto mucho mejor para las decisiones generales de diseño que la determinación de la orientación del dispositivo.

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


Publicación original:

Reemplace el método updateViewConstraints de UIViewController para proporcionar restricciones de diseño para situaciones específicas. De esta forma, el diseño siempre se configura de la manera correcta según la situación. Asegúrese de que forman un conjunto completo de restricciones con las creadas dentro del guión gráfico. Puede usar IB para configurar sus restricciones generales y marcar los objetos a cambiar para eliminarlos en tiempo de ejecución.

Utilizo la siguiente implementación para presentar un conjunto 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 activar 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 conjuntos de restricciones (vertical y horizontal) en el editor del guión gráfico.

Para evitar las advertencias del infierno, coloco todo un conjunto con una prioridad de 999, para que no se muestre rojo en todas partes.

Luego agrego todas las restricciones a las colecciones de salida:

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

Finalmente, implemento el método viewWillLayout mi ViewControllers :

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

Esto parece funcionar Realmente me gustaría poder establecer la propiedad activa predeterminada en el editor del guión gráfico.

Estoy siguiendo el mismo enfoque que el suyo (sin archivos de punta o guiones gráficos). updateViewConstraints actualizar sus restricciones en el método updateViewConstraints (verificando la orientación del dispositivo). No es necesario llamar a setNeedsUpdateConstraints en updateViewConstraints porque tan pronto como cambie la orientación del dispositivo, se llamará automáticamente al último método.

Puede guardar sus restricciones, a una propiedad o variable como versiones vertical y horizontal, y luego establecerlas y eliminarlas al rotarlas.

He hecho esto haciendo mis restricciones en xib para la vista inicial, asignándolas a salidas en el controlador de vista. Al rotar, creo las restricciones alternativas, elimino las salidas pero las retengo, inserto las alternativas.

Invierta el proceso al girar hacia atrás.

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

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

Paso 1: crea un diseño de paisaje (o retrato) en Storyboard con restricciones.
Paso 2: Para las restricciones, que deben estar activas solo para el modo de paisaje, establezca la 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.sharedApplication.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):

enter image description here

La interfaz se reconstruirá automáticamente.