Resortes en Diseño automático: Distribuya las vistas de manera uniforme, con restricciones, en Xcode 5


Entiendo el antiguo método de Struts and Springs para alinear, dimensionar y distribuir vistas en Interface Builder. Sin embargo, parece que no puedo averiguar cómo distribuir uniformemente las vistas utilizando el diseño automático con Xcode 5. Había una manera de hacerlo usando Xcode 4, pero esa opción se ha ido.

Tengo 7 botones dispuestos en una pila vertical. En un diseño de 3.5", se ve muy bien. Cuando previsualizo la pantalla en el diseño de 4", todos los botones permanecen apretados y hay una gran cantidad de espacio debajo del último botón.

Quiero que permanezcan a la misma altura, pero quiero que el espacio entre ellos pueda flexionarse para que puedan extenderse por la pantalla.

introduzca la descripción de la imagen aquí

He podido obtener la altura de los botones para flexionar y llenar el espacio, pero ese no es mi comportamiento deseado. Me gustaría aprender a usar el Diseño automático para reemplazar mi antiguo comportamiento de resortes, pero parece que no puedo encontrar ninguna manera de hacerlo a través de Interface Builder.

Estoy bien con el botón superior ya sea un espacio fijo desde el borde superior o un espacio proporcional desde el borde superior, del mismo modo para el botón inferior y el borde inferior. Esos son menos importantes para mí, estoy bien con cualquiera.

Pero realmente necesito averiguar cómo distribuir uniformemente el espacio adicional entre cada uno de los elementos de la vista.

Author: Kenny Wyland, 2014-01-01

2 answers

EDIT Tenga en cuenta que en iOS 9 esta técnica será innecesaria, porque un UIStackView realizará la distribución automáticamente. Añadiré otra respuesta explicando cómo funciona eso.

Cómo Realizar una Distribución Uniforme Usando Autolayout

La forma más sencilla de hacer esto solo en Interface Builder (en lugar de construir restricciones en código) es usar vistas "espaciadoras":

  1. Coloque los botones superior e inferior absolutamente.

  2. Coloque vistas espaciadoras entre todos los botones. Use restricciones para posicionarlos horizontalmente (centrarlos horizontalmente es más simple) y para establecer sus anchuras.

  3. Establezca restricciones entre cada botón y la vista espaciadora por encima y por debajo de él, con una Constante de 0.

  4. Ahora seleccione todas las vistas del espaciador y establezca sus alturas para que sean iguales.

La primera captura de pantalla me muestra configurando esto en IB:

introduzca la descripción de la imagen aquí

Deliberadamente no he corregido las "vistas fuera de lugar" porque quiero que veas cómo se ve mientras estoy diseñando las restricciones. Este es el resultado tanto en una pantalla de 4 pulgadas como en una de 3.5 pulgadas:

introduzca la descripción de la imagen aquí

He dejado las vistas del espaciador en negro, solo para mostrarle cómo funciona esta técnica, pero, por supuesto, en la vida real, ¡las haría transparentes y, por lo tanto, invisibles! Para que el usuario vea solo sus botones, distribuidos uniformemente en cualquier altura de pantalla.

La razón para el uso de esta técnica es que aunque la noción de igualdad realiza la distribución de los valores que está pidiendo, las restricciones pueden aplicar la igualdad solo entre aspectos de las vistas; por lo tanto, necesitamos las vistas adicionales (las vistas del espaciador) para que tengamos cosas que podamos hacer iguales a otras cosas (aquí, las alturas de las vistas del espaciador).

Otros enfoques

Obviamente, un enfoque más flexible es asignar las restricciones en el código. Esto puede sonar desalentador, pero hay un montón de código de terceros por ahí para ayudarle, como este tipo de cosas.

Por ejemplo, si tenemos una supervisión (posiblemente invisible) cuya altura actúa como un límite para dictar la distribución vertical máxima de nuestros cuatro botones, podemos fijar sus tapas al centro vertical de esa supervisión con un constant de 0 pero un multiplier de 0.000001, 0.666667, 1.33333, y 2.0 respectivamente (si tenemos cuatro botones); ahora los botones permanecerán distribuidos verticalmente incluso como el superview cambia de tamaño en respuesta a la altura de la pantalla o lo que sea. [En Xcode 5.1, será posible configurarlo en Interface Builder, pero en versiones anteriores de Xcode no es posible.]

 83
Author: matt,
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
2017-05-23 12:17:36

En iOS 9 / Xcode 7 este problema se resolverá trivialmente en IB. Simplemente seleccione los botones (o lo que sea que desee distribuir verticalmente) y elija Editor > Incrustar en > Vista de pila. A continuación, simplemente configure la vista de pila:

  • Proporcione restricciones que posicionen y dimensionen la propia vista de pila. Por ejemplo, fija los cuatro bordes de la vista de pila a los cuatro bordes de su supervisión.

  • Establece los atributos de la vista de pila. En este caso queremos eje Vertical, Alineación de relleno, Distribución de espaciado igual.

Eso es todo! Sin embargo, puede ser curioso acerca de cómo funciona esto, porque todavía es posible hacer lo mismo manualmente en el código. Una vista de pila realiza la distribución, no insertando spacer views, sino insertando spacer guides. Una guía (UILayoutGuide) es un objeto ligero que se comporta como una vista para fines de restricciones de diseño, pero no es una vista y, por lo tanto, no tiene que hacerse invisible y no lleva nada de lo alto de una vista.

Para ilustrar, haré en código lo que está haciendo la vista de pila. Supongamos que tenemos cuatro vistas para distribuir verticalmente. Les asignamos restricciones para todo menos para su distribución:

  • Todos tienen restricciones de altura absolutas

  • Su izquierda está anclada a la izquierda del superview, y su derecha está anclada a la derecha del superview

  • La parte superior de la vista superior está anclada a la parte superior de la supervisión, y la parte inferior de la vista inferior se fija a la parte inferior de la supervisión

Ahora, supongamos que tenemos referencias a las cuatro vistas como views, una matriz. Entonces:

let guides = [UILayoutGuide(), UILayoutGuide(), UILayoutGuide()]
for guide in guides {
    self.view.addLayoutGuide(guide)
}
NSLayoutConstraint.activateConstraints([
    // guide heights are equal
    guides[1].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
    guides[2].heightAnchor.constraintEqualToAnchor(guides[0].heightAnchor),
    // guide widths are arbitrary, let's say 10
    guides[0].widthAnchor.constraintEqualToConstant(10),
    guides[1].widthAnchor.constraintEqualToConstant(10),
    guides[2].widthAnchor.constraintEqualToConstant(10),
    // guide left is arbitrary, let's say superview margin
    guides[0].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
    guides[1].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
    guides[2].leftAnchor.constraintEqualToAnchor(self.view.leftAnchor),
    // bottom of each view is top of following guide
    views[0].bottomAnchor.constraintEqualToAnchor(guides[0].topAnchor),
    views[1].bottomAnchor.constraintEqualToAnchor(guides[1].topAnchor),
    views[2].bottomAnchor.constraintEqualToAnchor(guides[2].topAnchor),
    // top of each view is bottom of preceding guide
    views[1].topAnchor.constraintEqualToAnchor(guides[0].bottomAnchor),
    views[2].topAnchor.constraintEqualToAnchor(guides[1].bottomAnchor),
    views[3].topAnchor.constraintEqualToAnchor(guides[2].bottomAnchor)
])

(Obviamente podría hacer que el código sea más lindo y más corto usando bucles, pero he desenrollado deliberadamente los bucles para mayor claridad, para que pueda ver el patrón y la técnica.)

 9
Author: matt,
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-07-20 18:34:55