Sé que mucha gente ya hizo muchas preguntas sobre esto, pero incluso con las respuestas no puedo hacer que funcione.
Cuando estoy lidiando con restricciones en el guión gráfico, es fácil, pero en el código lo tengo difícil. Intento, por ejemplo, tener una vista que se quede en el lado derecho y tenga la altura de la pantalla según la orientación de la pantalla. Este es mi codigo:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
options:0 metrics:nil
views:NSDictionaryOfVariableBindings(myView)]];
No satisface algunas limitaciones. No veo lo que está mal. Además, ¿por qué no puedo usar una propiedad como en self.myView
lugar de una variable local como myView
?
objective-c
ios
constraints
autolayout
pierre23
fuente
fuente
myView
? (3) ¿Qué esvivi
(como preguntó ACB)? (4) ¿Tiene una propiedadmyView
declaradaself
?Respuestas:
Cuando se usa el diseño automático en el código, configurar el marco no hace nada. Por lo tanto, el hecho de que haya especificado un ancho de 200 en la vista anterior no significa nada cuando le establece restricciones. Para que el conjunto de restricciones de una vista no sea ambiguo, necesita cuatro cosas: una posición x, una posición y, un ancho y una altura para cualquier estado dado.
Actualmente, en el código anterior, solo tiene dos (altura, relativa a la supervista, y posición y, relativa a la supervista). Además de esto, tiene dos restricciones requeridas que podrían entrar en conflicto dependiendo de cómo se configuren las restricciones de la supervista de la vista. Si la supervista tuviera una restricción requerida que especifique que su altura debe tener un valor menor que 748, obtendrá una excepción de "restricciones insatisfactorias".
El hecho de que haya establecido el ancho de la vista antes de establecer restricciones no significa nada. Ni siquiera tendrá en cuenta el marco anterior y calculará un marco nuevo en función de todas las restricciones que ha especificado para esas vistas. Cuando trato con el diseño automático en el código, normalmente solo creo una nueva vista usando
initWithFrame:CGRectZero
o simplementeinit
.Para crear el conjunto de restricciones requerido para el diseño que describió verbalmente en su pregunta, necesitaría agregar algunas restricciones horizontales para delimitar el ancho y la posición x para dar un diseño completamente especificado:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]];
La descripción verbal de este diseño es la siguiente, comenzando con la restricción vertical:
Si simplemente desea que la vista llene la altura de la supervista completa sin restringir la altura de la supervista, entonces simplemente omitiría el
(>=748)
parámetro en el texto del formato visual. Si cree que el(>=748)
parámetro es necesario para darle una altura, no lo hace en este caso: anclar la vista a los bordes de la supervista usando la barra (|
) o la barra con espacio (|-
,-|
sintaxis de ), está dando su vista a y -posición (fijar la vista en un solo borde) y una posición y con altura (fijar la vista en ambos bordes), satisfaciendo así su conjunto de restricciones para la vista.En cuanto a su segunda pregunta:
Utilizando
NSDictionaryOfVariableBindings(self.myView)
(si tuviera una configuración de propiedad para myView) y la alimentación que en su VFL a utilizarself.myView
en el texto VFL, es probable que obtener una excepción cuando autolayout intenta analizar el texto VFL. Tiene que ver con la notación de puntos en las claves del diccionario y el sistema que intenta usarvalueForKeyPath:
. Vea aquí una pregunta y una respuesta similares .fuente
Hola, he estado usando mucho esta página para conocer las limitaciones y el "cómo". Me tomó una eternidad llegar al punto de darme cuenta de que necesitaba:
myView.translatesAutoresizingMaskIntoConstraints = NO;
para que este ejemplo funcione. Gracias Userxxx, Rob M. y especialmente larsacus por la explicación y el código aquí, ha sido invaluable.
Aquí está el código completo para ejecutar los ejemplos anteriores:
UIView *myView = [[UIView alloc] init]; myView.backgroundColor = [UIColor redColor]; myView.translatesAutoresizingMaskIntoConstraints = NO; //This part hung me up [self.view addSubview:myView]; //needed to make smaller for iPhone 4 dev here, so >=200 instead of 748 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]];
fuente
Versión rápida
Actualizado para Swift 3
Este ejemplo mostrará dos métodos para agregar mediante programación las siguientes restricciones de la misma manera que si lo hiciera en Interface Builder:
Anchura y altura
Centro en contenedor
Código repetitivo
override func viewDidLoad() { super.viewDidLoad() // set up the view let myView = UIView() myView.backgroundColor = UIColor.blue myView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(myView) // Add constraints code here (choose one of the methods below) // ... }
Método 1: estilo de ancla
// width and height myView.widthAnchor.constraint(equalToConstant: 200).isActive = true myView.heightAnchor.constraint(equalToConstant: 100).isActive = true // center in container myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Método 2: Estilo NSLayoutConstraint
// width and height NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true // center in container NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
Notas
NSLayoutConstraint
estilo, sin embargo, solo está disponible en iOS 9, por lo que si es compatible con iOS 8, debe usarNSLayoutConstraint
Style.fuente
Con respecto a su segunda pregunta sobre propiedades, puede usar
self.myView
solo si la declaró como propiedad en la clase. Dado quemyView
es una variable local, no puede usarla de esa manera. Para obtener más detalles sobre esto, le recomendaría que consulte la documentación de Apple sobre Propiedades declaradas ,fuente
¿Por qué no puedo usar una propiedad como en
self.myView
lugar de una variable local como myView?intente usar:
NSDictionaryOfVariableBindings(_view)
en vez de
self.view
fuente
Tenga en cuenta también que desde iOS9 podemos definir restricciones mediante programación "más concisas y más fáciles de leer" utilizando subclases de la nueva clase auxiliar NSLayoutAnchor .
Un ejemplo del documento:
[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
fuente