Creación de restricciones de layout mediante progtwigción

Sé que mucha gente ya ha hecho muchas preguntas al respecto, 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 encuentro difícil. Intento, por ejemplo, tener una vista que se mantenga en el lado derecho y que tenga la altura de la pantalla según la orientación de la pantalla. Este es mi código:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)]; myView.backgroundColor = [UIColor networkingColor]; [self.view addSubview:myView]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; 

No satisface algunas restricciones. No veo lo que está mal. Además, ¿por qué no puedo usar una propiedad como self.myView lugar de una variable local como myView ?

Cuando se utiliza el layout automático en el código, la configuration del marco no hace nada. Entonces, el hecho de que especificó un ancho de 200 en la vista anterior, no significa nada cuando establece restricciones en él. Para que el set de restricciones de una vista sea inequívoco, necesita cuatro cosas: una position x, una position y, un ancho y una altura para cualquier estado dado.

Actualmente, en el código anterior, solo tiene dos (altura, relativa a la vista de supervisión y position y, en relación con la vista de supervisión). Además de esto, tiene dos restricciones obligatorias que pueden entrar en conflicto según cómo se configuren las restricciones de la supervisión de la vista. Si la vista de supervisión tuviera una restricción requerida que especifica que su altura sea un valor menor a 748, obtendrá una exception de "restricciones insatisfactorias".

El hecho de que haya establecido el ancho de la vista antes de establecer restricciones no significa nada. Ni siquiera tomará en count el marco antiguo y calculará un nuevo marco basado en todas las restricciones que ha especificado para esas vistas. Cuando trato con autolayout en código, normalmente solo creo una nueva vista usando initWithFrame:CGRectZero o simplemente init .

Para crear el set de restricciones requerido para el layout que describió verbalmente en su pregunta, debería agregar algunas restricciones horizontales para unir el ancho y la position x para proporcionar un layout totalmente 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 layout se lee de la siguiente manera comenzando con la restricción vertical:

myView llenará la altura de su supervisor con un relleno superior e inferior igual al espacio estándar. La supervisión de myView tiene una altura mínima de 748pts. El ancho de myView es de 200pts y tiene un relleno derecho igual al espacio estándar frente a su supervisión.

Si simplemente desea que la vista complete la altura de toda la supervisión sin restringir la altura de la supervisión, omita el parámetro (>=748) en el text del formatting visual. Si cree que el parámetro (>=748) es necesario para darle una altura, no lo hace en esta instancia: fijar la vista a los bordes de la vista de supervisión utilizando la barra ( | ) o la barra con espacio ( |- , -| ), le está dando a su vista una position y (fijando la vista en un solo borde), y una position y con altura (fijando la vista en ambos bordes), satisfaciendo así su set de restricciones para la vista.

Con respecto a su segunda pregunta:

Si utiliza NSDictionaryOfVariableBindings(self.myView) (si tenía una configuration de propiedad para myView) y lo introdujo en su VFL para usar self.myView en su text VFL, es probable que obtenga una exception cuando autolayout intenta analizar su text VFL. Tiene que ver con la notación de puntos en las keys del dictionary y el sistema que intenta usar valueForKeyPath: Vea aquí una pregunta y una respuesta similar .

Hola, he estado usando esta página mucho para las restricciones y "cómo". Me tomó una eternidad llegar al punto de darse count 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 get los ejemplos anteriores para ejecutar:

 UIView *myView = [[UIView alloc] init]; myView.backgroundColor = [UIColor networkingColor]; 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)]]; 

Versión Swift

Actualizado para Swift 3

Este ejemplo mostrará dos methods para agregar de forma programática las siguientes restricciones igual que si lo hiciera en el Generador de interfaces:

Anchura y altura

introduzca la descripción de la imagen aquí

Centro en contenedor

introduzca la descripción de la imagen aquí

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 anclaje

 // 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

  • El estilo de anclaje es el método preferido sobre NSLayoutConstraint Style, sin embargo, solo está disponible desde iOS 9, por lo que si está soportando iOS 8, debería seguir utilizando NSLayoutConstraint Style.
  • Consulte también la documentation para crear restricciones de progtwigción .
  • Vea esta respuesta para un ejemplo similar de agregar una restricción de fijación.

Con respecto a su segunda pregunta sobre properties, puede usar self.myView solo si la declaró como propiedad en class. Como myView es una variable local, no puede usarlo de esa manera. Para más detalles sobre esto, le recomiendo que revise la documentation de Apple en Propiedades declaradas ,

¿Por qué no puedo usar una propiedad como self.myView lugar de una variable local como myView?

intente usar:

 NSDictionaryOfVariableBindings(_view) 

en lugar de self.view

Tenga en count también que desde iOS9 podemos definir restricciones programáticamente "más concisas y fáciles de leer" utilizando subclasss de la nueva class auxiliar NSLayoutAnchor .

Un ejemplo del doc:

 [self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;