2012-10-10 22 views
82

Sé que muchas personas ya hicieron muchas preguntas al respecto, pero incluso con las respuestas no puedo hacerlo funcionar.Creando restricciones de diseño programáticamente

Cuando estoy lidiando con restricciones en el guión gráfico, es fácil pero en el código tengo dificultades. Intento, por ejemplo, tener una vista que permanezca 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 redColor]; 
[self.view addSubview:myView]; 
[self.view addConstraints:[NSLayoutConstraint 
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" 
    options:0 metrics:nil 
    views:NSDictionaryOfVariableBindings(myView)]]; 

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

+0

Lo que es vivi en el código anterior? – iDev

+13

Cambie el título a "iOS" en lugar de "IOS": este último se refiere al sistema operativo de conmutador/enrutador de Cisco. Me confundió. Gracias. – armani

+1

Varias preguntas sobre esto: (1) ¿Qué error está obteniendo cuando "no satisface algunas restricciones"? (2) ¿Está traduciendo el autoajuste a restricciones en 'myView'? (3) ¿Qué es 'vivi' (como preguntó ACB)? (4) ¿Tiene una propiedad 'myView' declarada en' self'? – Tim

Respuesta

105

Al usar el diseño automático en el código, al establecer el marco no se hace nada. Por lo tanto, el hecho de que haya especificado un ancho de 200 en la vista anterior no significa nada cuando establece restricciones en él. Para que la restricción de una vista sea inequívoca, 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 (alto, relativo a la supervista, y posición y, relativo a la supervista). Además de esto, tiene dos restricciones obligatorias que podrían entrar en conflicto dependiendo de cómo se configuran las restricciones de la vista de la vista. Si la supervista tuvieran una restricción requerida que especifique que su altura sea un valor inferior a 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 tomará en cuenta el marco anterior y calculará un nuevo marco basado en todas las restricciones que ha especificado para esas vistas. Cuando se trata de autolayout en el código, normalmente solo creo una nueva vista usando initWithFrame:CGRectZero o simplemente init.

Para crear el conjunto de restricciones necesarias para la composición que ha descrito verbalmente en su pregunta, usted tendría que añadir algunas restricciones horizontales para limitar el ancho y la posición X con el fin de darle un diseño completamente especificada:

[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)]]; 

verbalmente describir esta disposición dice lo siguiente a partir de la restricción vertical:

myView llenará la altura de su supervista con un acolchado superior e inferior igual al espacio estándar. La supervista de myView tiene una altura mínima de de 748pts. El ancho de myView es de 200pts y tiene un margen derecho igual a el espacio estándar contra su superview.

Si simplemente como el fin de llenar la altura de toda la supervista sin limitar la altura de la supervista, entonces sería simplemente omitir el parámetro (>=748) en el texto formato visual.Si cree que se necesita el parámetro (>=748) para darle una altura, no lo hace en esta instancia: fijando la vista a los bordes de la supervista usando la barra (|) o la barra con espacio (|-, -|) sintaxis, está dando su vista en una posición y (fijando la vista en un solo borde), y una posición y en altura (fijando la vista en ambos bordes), satisfaciendo así su conjunto de restricciones para la vista.

En lo que respecta a su segunda pregunta:

Uso NSDictionaryOfVariableBindings(self.myView) (si tuviera una configuración de propiedad para myView) y la alimentación que en su VFL utilizar self.myView en su texto VFL, es probable que obtener una excepción cuando autolayout intentos para analizar su texto VFL. Tiene que ver con la notación de punto en las teclas del diccionario y el sistema que intenta usar valueForKeyPath:. See here for a similar question and answer.

+0

No olvide que algunos objetos como UILabel tienen un tamaño intrínseco y no es necesario establecer el ancho o alto de ese objeto, solo su posición. Sin embargo, si establece la altura o el ancho, creo que elimina ambos y luego debe proporcionar ambos. –

+0

Aunque esta respuesta no respondió mi pregunta, me ayudó a darme cuenta de algo. ¡Gracias por ser! :) –

+1

La única presentación de diseño automático conciso y legible en Internet hasta el momento. –

5

En cuanto a su segunda pregunta sobre las propiedades, puede usar self.myView solo si la declaró como una propiedad en la clase. Como myView es una variable local, no puede usarlo de esa manera. Para obtener más detalles al respecto, le recomiendo que consulte la documentación de Apple en Declared Properties,

60

Hola He estado usando esta página mucho para las restricciones y "cómo hacerlo". Me llevó una eternidad llegar al punto de darme cuenta de que necesitaba:

myView.translatesAutoresizingMaskIntoConstraints = NO; 

para hacer funcionar este ejemplo. Gracias Userxxx, Rob M. y especialmente larsacus por la explicación y el código aquí, ha sido invaluable.

Este es el código en su totalidad para conseguir los ejemplos anteriores para funcionar:

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)]]; 
5

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

intento usando:

NSDictionaryOfVariableBindings(_view) 

en lugar de self.view

+0

Eso hace que mi aplicación se cuelgue, da mensaje: 'No se puede analizar el formato de restricción: polylineImageView no es una clave en el diccionario de vistas.' –

4

Tenga en cuenta también que a partir de iOS9 podemos definir restricciones de programación "más concisa y fácil de leer" utilizando subclases de la nueva clase de ayuda NSLayoutAnchor.

Un ejemplo del documento:

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

gracias por el '.active = true' –

9

versión Swift

Actualización de Swift 3

Este ejemplo se muestran dos métodos para agregar mediante programación las siguientes limitaciones lo mismo que si al hacerlo en el Interface Builder:

anchura y altura

enter image description here

Center en Container

enter image description here

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: Ancla Estilo

// 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: NSLayoutConstraint Estilo

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

  • estilo ancla es el método preferido sobre NSLayoutConstraint estilo, sin embargo, sólo está disponible en iOS 9, por lo que si usted está apoyando iOS 8 entonces todavía deberías usar el estilo NSLayoutConstraint.
  • Véase también la documentación Programmatically Creating Constraints.
  • Consulte this answer para obtener un ejemplo similar de cómo agregar una restricción de fijación.
Cuestiones relacionadas