ios - español - stack view swift 4
¿Puedo usar autolayout para proporcionar diferentes restricciones para las orientaciones horizontal y vertical? (5)
¿Es posible cambiar las restricciones cuando se gira el dispositivo? ¿Cómo podría lograrse esto?
Un ejemplo simple podría ser dos imágenes que, en vertical, se apilan una sobre la otra, pero en horizontal están una al lado de la otra.
Si esto no es posible, ¿de qué otra manera podría lograr este diseño?
Estoy construyendo mis vistas y restricciones en el código y no estoy usando el generador de interfaces.
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 en el guión gráfico, coloco todos los conjuntos a una prioridad de 999, solo para que no aparezcan rojos en todas partes.
Luego agrego todas las restricciones a las colecciones de outlet:
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;
Finalmente, implemento el método viewWillLayout
mis 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 deseo que puedas establecer la propiedad activa predeterminada en el editor del guión gráfico.
Mi idea es manejar la orientación cambiando las prioridades de restricción.
Suponiendo que las prioridades serán:
- Paisaje: 910 activos / 10 inactivos.
- retrato: 920 activos / 20 inactivos.
Paso 1: Crear diseño de paisaje (o retrato) en el Guión gráfico con restricciones.
Paso 2: para restricciones, debe estar activo solo para el modo horizontal, establecer la prioridad en 10.
Paso 3: Agregue restricciones para el modo retrato y establezca su prioridad en 920.
En willAnimateRotationToInterfaceOrientation
agrega el 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: ajuste fácil 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):
La interfaz se reconstruirá automáticamente.
Puede guardar sus restricciones, en una propiedad o variable como versiones verticales y horizontales, luego configurarlas y eliminarlas en la rotación.
He hecho esto haciendo mis restricciones en xib para la vista inicial, asignándolas a puntos de venta en el controlador de vista. Al girar, creo las restricciones alternativas, elimino las salidas pero las retengo, inserto las alternativas.
Invierta el proceso al girar hacia atrás.
Sigo el mismo enfoque que el tuyo (no hay archivos de plumillas ni 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 cambia la orientación del dispositivo, se llama automáticamente al último método.
Edición: Al utilizar 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 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 para determinar la orientación del dispositivo.
Dicho esto, si realmente necesita conocer la orientación, 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 manera, el diseño siempre se configura de manera correcta según la situación. Asegúrese de que formen un conjunto completo de restricciones con las creadas dentro del guión gráfico. Puede usar IB para configurar sus restricciones generales y marcar aquellos sujetos a cambios que se eliminarán 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, e.g.:
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 la situación cambie. willAnimateRotationToInterfaceOrientation:duration:
para animar la actualización de la restricción en el cambio de orientación:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.view setNeedsUpdateConstraints];
}