ios8 - para - Implementando mediante programación dos diseños diferentes utilizando clases de tamaño
ios 8 para iphone 4s (4)
Tengo un diseño de cuatro botones. En el retrato, deberían mostrarse uno encima del otro. En el paisaje, deberían estar en dos columnas, cada una con dos botones.
Implemento los botones en código: cosas realmente simples:
UIButton *btn1 = [[UIButton alloc] init];
[self.view addSubview: btn1];
UIButton *btn2 = [[UIButton alloc] init];
[self.view addSubview: btn2];
UIButton *btn3 = [[UIButton alloc] init];
[self.view addSubview: btn3];
UIButton *btn4 = [[UIButton alloc] init];
[self.view addSubview: btn4];
NSDictionary *views = NSDictionaryOfVariableBindings(btn1, btn2, btn3, btn4);
[btn1 setTranslatesAutoresizingMaskIntoConstraints:NO];
[btn2 setTranslatesAutoresizingMaskIntoConstraints:NO];
[btn3 setTranslatesAutoresizingMaskIntoConstraints:NO];
[btn4 setTranslatesAutoresizingMaskIntoConstraints:NO];
// portrait constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn1]-(50)-|"
options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn2]-(50)-|"
options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn3]-(50)-|"
options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(50)-[btn4]-(50)-|"
options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[btn1]-[btn2]-[btn3]-[btn4]-(50)-|"
options:0 metrics:nil views:views]];
Esta es obviamente la configuración para el diseño de retrato. Solía haber determinado el dispositivo y su orientación para hacer un caso específico para iPad y iPhone en las respectivas orientaciones. Pero ahora se supone que debemos usar clases de tamaño. ¿Cómo puedo determinar si la clase de tamaño es "compacta" ... y establecer las restricciones apropiadas?
Código de Swift 4 para la respuesta aceptada:
if (self.view.traitCollection.horizontalSizeClass == .compact) {
...
}
Mientras tanto, he encontrado una buena solución. Dado que esta pregunta tiene tantos votos positivos, pensé que la describiría rápidamente. Me inspiró esta solución en una sesión de WWDC.
Me he mudado a Swift, por favor disculpe que el código sea rápido, sin embargo, el concepto es el mismo para Obj-C.
Comienzas declarando tres matrices de restricciones:
// Constraints
private var compactConstraints: [NSLayoutConstraint] = []
private var regularConstraints: [NSLayoutConstraint] = []
private var sharedConstraints: [NSLayoutConstraint] = []
Y luego llenas las restricciones en consecuencia. Puede hacer esto en una función separada a la que llama desde viewDidLoad
o lo hace en viewDidLoad
directamente.
sharedConstraints.append(contentsOf: [
btnStackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
...
])
compactConstraints.append(contentsOf: [
btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7),
...
])
regularConstraints.append(contentsOf: [
btnStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.4),
...
])
La parte importante es cambiar entre las clases de tamaño y activar / desactivar las restricciones apropiadas.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if (!sharedConstraints[0].isActive) {
// activating shared constraints
NSLayoutConstraint.activate(sharedConstraints)
}
if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular {
if regularConstraints.count > 0 && regularConstraints[0].isActive {
NSLayoutConstraint.deactivate(regularConstraints)
}
// activating compact constraints
NSLayoutConstraint.activate(compactConstraints)
} else {
if compactConstraints.count > 0 && compactConstraints[0].isActive {
NSLayoutConstraint.deactivate(compactConstraints)
}
// activating regular constraints
NSLayoutConstraint.activate(regularConstraints)
}
}
Sé que las restricciones no se ajustan a las de la pregunta. Pero las restricciones en sí mismas son irrelevantes. Lo principal es cómo uno cambia entre dos conjuntos de restricciones en función de la clase de tamaño.
Espero que esto ayude.
Puede examinar la colección de rasgos de la vista para determinar su clase de tamaño horizontal y vertical.
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
...
}
Implemente el método traitCollectionDidChange:
para llamar automáticamente cuando un rasgo cambia debido a la autorrotación.
Para obtener más información, consulte UITraitCollection Class Reference y UITraitEnvironment Protocol Reference .
TraitCollection solo funciona en iOS8. Entonces tu aplicación se bloqueará en iOS7. Use el siguiente código para admitir iOS7 e iOS8
if ([self.view respondsToSelector:@selector(traitCollection)]){
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
...
}
}