Centrar una vista en su vista de supervisión utilizando el lenguaje de formatting visual

Acabo de comenzar a aprender AutoLayout para iOS y eché un vistazo a Visual Format Language.

Todo funciona bien a exception de una cosa: simplemente no puedo hacer que una vista se centre dentro de su supervisión.
¿Esto es posible con VFL o debo crear manualmente una restricción?

Actualmente, no, no parece que sea posible centrar una vista en la vista de supervisión usando solo VFL. Sin embargo, no es tan difícil hacerlo usando una única cadena VFL y una única restricción extra (por eje):

VFL: "|-(>=20)-[view]-(>=20)-|"

 [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:view.superview attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]; 

Uno pensaría que simplemente podría hacer esto (que es lo que inicialmente pensé y probé cuando vi esta pregunta):

 [NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=20)-[view(==200)]-(>=20)-|" options: NSLayoutFormatAlignAllCenterX | NSLayoutFormatAlignAllCenterY metrics:nil views:@{@"view" : view}]; 

Probé muchas variaciones diferentes de lo anterior tratando de doblarlo a mi voluntad, pero esto no parece aplicarse a la supervisión, incluso cuando explícitamente tiene dos cadenas VFL separadas para ambos ejes ( H:|V: :). Entonces empecé a tratar de aislar exactamente cuando las opciones se aplican al VFL. Parece que no se aplican a la supervisión en el VFL y solo se aplicarán a las vistas explícitas que se mencionan en la cadena VFL (lo cual es decepcionante en ciertos casos).

Espero que en el futuro Apple agregue algún tipo de nueva opción para que las opciones de VFL tengan en count la supervisión, incluso si lo hacen solo cuando hay una sola vista explícita además de la supervisión en VFL. Otra solución podría ser otra opción que se pasa al VFL que dice algo como: NSLayoutFormatOptionIncludeSuperview .

Huelga decir que aprendí mucho acerca de VFL tratando de responder a esta pregunta.

Sí, es posible centrar una vista en su supervisión con Visual Format Language. Tanto vertical como horizontalmente. Aquí está la demo:

https://github.com/evgenyneu/center-vfl

Creo que es mejor crear restricciones manualmente.

 [superview addConstraint: [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; [superview addConstraint: [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; 

Ahora podemos usar NSLayoutAnchor para definir automáticamente AutoLayout :

(Disponible en iOS 9.0 y posterior)

 view.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true view.centerYAnchor.constraint(equalTo: superview.centerYAnchor).isActive = true 

Recomiendo el uso de SnapKit , que es un DSL para facilitar el layout automático en iOS y macOS.

 view.snp.makeConstraints({ $0.center.equalToSuperview() }) 

Absolutamente posible fue capaz de hacerlo así:

 [NSLayoutConstraint constraintsWithVisualFormat:@"H:[view]-(<=1)-[subview]" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(view, subview)]; 

Aprendí esto desde aquí. El código anterior centra la subvista en vista por Y obviamente.

Swift3:

  NSLayoutConstraint.constraints(withVisualFormat: "H:[view]-(<=1)-[subview]", options: .alignAllCenterY, metrics: nil, views: ["view":self, "subview":_spinnerView]) 

Agregue el código a continuación y haga que su button esté en el centro de la pantalla. Absolutamente posible

 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button]-|" options:NSLayoutFormatAlignAllCenterY metrics:0 views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[button]-|" options:NSLayoutFormatAlignAllCenterX metrics:0 views:views]]; 

Sé que no quiere que lo desees, pero por supuesto puedes calcular los márgenes y usarlos para crear la cadena de formatting visual;)

De todos modos, no Desafortunadamente, no es posible hacer eso 'automáticamente' con VFL, al less aún no.

Lo que hay que hacer es que la supervisión debe declararse en el dictionary. En lugar de usar | usas @{@"super": view.superview}; .

Y NSLayoutFormatAlignAllCenterX para vertical y NSLayoutFormatAlignAllCenterY para opciones horizontales como.

Puedes usar vistas adicionales.

 NSDictionary *formats = @{ @"H:|[centerXView]|": @0, @"V:|[centerYView]|": @0, @"H:[centerYView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterY), @"V:[centerXView(0)]-(>=0)-[yourView]": @(NSLayoutFormatAlignAllCenterX), }; NSDictionary *views = @{ @"centerXView": centerXView, @"centerYView": centerYView, @"yourView": yourView, }; ^(NSString *format, NSNumber *options, BOOL *stop) { [superview addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:format options:options.integerValue metrics:nil views:views]]; }]; 

Si lo desea limpio, entonces centerXView.hidden = centerYView.hidden = YES; .

PD: No estoy seguro de poder llamar a los "marcadores de position" de las vistas adicionales, porque el inglés es mi segundo idioma. Se agradecerá si alguien me puede decir eso.

Para aquellos que vinieron aquí para una solución basada en el Interface Builder (Google me lleva aquí), simplemente agregue las restricciones const width / height, y select la subview -> control drag a su superview -> select "center vertical / horizontal in superview".

@ igor-muzyka respuesta en Swift :

 NSLayoutConstraint.constraintsWithVisualFormat("H:[view]-(<=1)-[subview]", options: .AlignAllCenterY, metrics: nil, views: ["view":view, "subview":subview]) 

Gracias a la respuesta de @Evgenii, creo un ejemplo completo en esencia:

centrar el cuadrado rojo verticalmente con altura personalizada

https://gist.github.com/yallenh/9fc2104b719742ae51384ed95dcaf626

Puede centrar una vista verticalmente utilizando VFL (que no es muy intuitivo) o usar restricciones manualmente. Por cierto, no puedo combinar el centro y la altura juntos en VFL como:

 "H:[subView]-(<=1)-[followIcon(==customHeight)]" 

En la solución actual, las restricciones VFL se agregan por separado.

Solo necesito decir que puedes usar esto en lugar de restricciones:

 child.center = [parent convertPoint:parent.center fromView:parent.superview]; 

En lugar de usar VFL, puede hacer esto fácilmente en el generador de interfaces. En el Storyboard principal, presione + clic en la vista que desea centrar. Arrastre a la vista de supervisión (mientras mantiene presionada la tecla ctrl) y select "Centro X" o "Centro Y". No se necesita un codigo