iOS-Posiciona UIView en el centro de superview usando Auto Layout programáticamente


¿Cómo se configura programáticamente una UIView para que esté en el centro de su superview usando Auto Layout?

UIButton* viewObj = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[viewObj setTranslatesAutoresizingMaskIntoConstraints:NO];
[viewObj setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:viewObj];

NSLayoutConstraint* cn = [NSLayoutConstraint constraintWithItem:viewObj
                                                      attribute:NSLayoutAttributeCenterX
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeCenterX 
                                                     multiplier:1.0
                                                       constant:0];
[self.view addConstraint:cn];
cn = [NSLayoutConstraint constraintWithItem:viewObj 
                                  attribute:NSLayoutAttributeCenterY
                                  relatedBy:NSLayoutRelationEqual 
                                     toItem:self.view
                                  attribute:NSLayoutAttributeCenterY
                                 multiplier:1.0
                                   constant:0];
[self.view addConstraint:cn];

El código anterior funciona para mí para UIButton, pero estoy teniendo problemas para reemplazar la primera línea con algo que funcione para un UIView.

He intentado

UIView* viewObj = [UIView alloc] initWithFrame:CGRectZero];

Pero la vista no aparece en el simulador.

Alguna sugerencia?

Gracias!

Author: John Topley, 2012-12-23

2 answers

Dado que hizo esta pregunta en el contexto de usar Auto Layout, el problema aquí es que un UIButton tiene un tamaño intrínseco (comunicado a través del método intrinsicContentSize) que proporciona Auto Layout con información sobre ancho y alto, pero una UIView normalmente no lo hace. Por lo tanto, debe agregar más restricciones relacionadas con el ancho y la altura.

Si desea que su UIView sea un tamaño establecido (digamos, 200x200), puede agregar estas líneas:

cn = [NSLayoutConstraint constraintWithItem:viewObj 
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual 
                                     toItem:nil
                                  attribute:NSLayoutAttributeNotAnAttribute 
                                 multiplier:1
                                   constant:200];
[viewObj addConstraint:cn];

cn = [NSLayoutConstraint constraintWithItem:viewObj
                                  attribute:NSLayoutAttributeWidth
                                  relatedBy:NSLayoutRelationEqual
                                     toItem:nil
                                  attribute:NSLayoutAttributeNotAnAttribute 
                                 multiplier:1 
                                   constant:200];
[viewObj addConstraint: cn];

Tenga en cuenta que el argumento toItem: es nil y el segundo atributo es NSLayoutAttributeNotAnAttribute, porque no está especificando el ancho y el alto en relación con nada más. Si desea que la altura y el ancho del subview sean relativos al superview (digamos, 0.5), puede hacer esto:

cn = [NSLayoutConstraint constraintWithItem:viewObj
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                     toItem:self.view
                                  attribute:NSLayoutAttributeHeight 
                                 multiplier:0.5 
                                   constant:0];
[self.view addConstraint:cn];
cn = [NSLayoutConstraint constraintWithItem:viewObj
                                  attribute:NSLayoutAttributeWidth
                                  relatedBy:NSLayoutRelationEqual
                                     toItem:self.view
                                  attribute:NSLayoutAttributeWidth
                                 multiplier:0.5
                                   constant:0];
[self.view addConstraint: cn];
 21
Author: Peter E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-11 07:31:44

UIButton, UIImageView, UIlabel y UITextField puede establecer automáticamente su tamaño de acuerdo con sus propiedades de contenido. El ancho y la altura de un UIImageView se establecen por el UIImage que puede contener. El tamaño de un UILabel dependerá de su texto. El ancho y el alto de un UIButton están definidos por el título y la imagen que tiene (puede obtener más información sobre él con Intrínsecamente Content Size).

Por lo tanto, cuando desea centrar a UIButton, a UILabel, a UITextField o a UIImageView dentro de a UIView con diseño automático, en casi todos los casos no tiene que crear restricciones para su ancho y altura. Simplemente necesita establecer restricciones horizontales y verticales para ellos.

Sin embargo, con auto layout, un UIView que no tiene subviews no puede confiar en nada para establecer su tamaño a menos que le proporcione algunas restricciones arbitrarias de ancho y altura. Y de acuerdo con sus necesidades, puede resolver esto de 3 maneras diferentes.


El estilo de diseño automático puro

Aquí, establecemos el ancho y la altura de nuestro UIView directamente como restricciones de diseño automático:

override func viewDidLoad() {
    super.viewDidLoad()

    let newView = UIView()
    newView.backgroundColor = .redColor()
    newView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(newView)

    // Auto layout code using anchors (iOS9+)
    let horizontalConstraint = newView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor)
    let verticalConstraint = newView.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor)
    let widthConstraint = newView.widthAnchor.constraintEqualToAnchor(nil, constant: 100)
    let heightConstraint = newView.heightAnchor.constraintEqualToAnchor(nil, constant: 100)
    NSLayoutConstraint.activateConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}

El estilo de máscara autoresizing

Aquí inicializamos nuestro UIView con su ancho y alto, hacemos que su centro y el centro de su superview sean iguales y creamos algunas máscaras autoresizing. Luego, le pedimos a UIKit que traduzca esas máscaras de autoresizing en restricciones de diseño automático:

override func viewDidLoad() {
    super.viewDidLoad()

    let newView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
    newView.backgroundColor = .redColor()

    newView.center = CGPointMake(view.bounds.midX, view.bounds.midY)
    newView.autoresizingMask = [.FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin, .FlexibleBottomMargin]

    newView.translatesAutoresizingMaskIntoConstraints = true // default is true
    view.addSubview(newView)
}

El estilo de subclase

Aquí, creamos una subclase de UIView y anulamos su método intrinsicContentSize() ( declaración ) que devuelve el tamaño deseado:

import UIKit

class CustomView: UIView {
    override func intrinsicContentSize() -> CGSize {
        return CGSize(width: 100, height: 100)
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let newView = CustomView()
        newView.backgroundColor = .redColor()
        newView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(newView)

        let horizontalConstraint = NSLayoutConstraint(item: newView,
            attribute: .CenterX,
            relatedBy: .Equal,
            toItem: view,
            attribute: .CenterX,
            multiplier: 1,
            constant: 0)
        view.addConstraint(horizontalConstraint)
        let verticalConstraint = NSLayoutConstraint(item: newView,
            attribute: .CenterY,
            relatedBy: .Equal,
            toItem: view,
            attribute: .CenterY,
            multiplier: 1,
            constant: 0)
        view.addConstraint(verticalConstraint)
    }

}
 3
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-27 22:45:59