Espaciar uniformemente varias vistas dentro de una vista de contenedor


El diseño automático me está haciendo la vida difícil. En teoría, iba a ser muy útil cuando cambié, pero parece que lucho todo el tiempo.

He hecho un proyecto de demostración para tratar de encontrar ayuda. ¿Alguien sabe cómo hacer que los espacios entre vistas aumenten o disminuyan uniformemente cada vez que se redimensiona la vista?

Aquí hay tres etiquetas (manualmente espaciadas verticalmente incluso):

image1

Lo que quiero es que redimensionen su espaciado (no el tamaño de la vista) de manera uniforme cuando girar. De forma predeterminada, las vistas superior e inferior se aplastan hacia el centro:

image2

Author: paulmelnikow, 2012-10-25

27 answers

Así que mi enfoque le permite hacer esto en interface builder. Lo que haces es crear 'vistas espaciadoras' que has configurado para que coincidan con las alturas por igual. A continuación, agregue restricciones superiores e inferiores a las etiquetas (vea la captura de pantalla).

introduzca la descripción de la imagen aquí

Más específicamente, tengo una restricción superior en 'Vista Espaciadora 1' para supervision con una restricción de altura de menor prioridad que 1000 y con Altura Igual a todas las otras 'vistas espaciadoras'. 'Spacer View 4' tiene una restricción de espacio inferior para supervision. Cada etiqueta tiene sus respectivas restricciones superior e inferior a sus 'vistas espaciadoras' más cercanas.

Nota: Asegúrese de NO tener restricciones de espacio superior/inferior adicionales en sus etiquetas para superponer; solo las de las 'vistas de espacio'. Esto se puede satisfacer ya que las restricciones superior e inferior están en 'Vista de espacio 1' y 'Vista espaciadora 4' respectivamente.

Duh 1: Duplicé mi vista y simplemente la puse en modo horizontal para que pudieran ver que funcionaba.

Duh 2: Las' vistas del espaciador ' podrían han sido transparentes.

Duh 3: Este enfoque podría aplicarse horizontalmente.

 200
Author: Spencer Hall,
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-03-11 19:51:57

¡MIRA, NADA DE ESPACIADORES!

Basado en las sugerencias en la sección de comentarios de mi respuesta original, especialmente las sugerencias útiles de @Rivera, he simplificado mi respuesta original.

Estoy usando gifs para ilustrar lo simple que es esto. Espero que los gifs te sean útiles. En caso de que tengas un problema con los gifs, he incluido la antigua respuesta a continuación con capturas de pantalla simples.

Instrucciones:

1) Añade tus botones o etiquetas. Estoy usando 3 botón.

2) Agregue una restricción center x de cada botón a la superview:

introduzca la descripción de la imagen aquí

3) Agregue una restricción de cada botón a la restricción de diseño inferior:

introduzca la descripción de la imagen aquí

4) Ajuste la restricción agregada en #3 de la siguiente manera:

a) seleccione la restricción, b) elimine la constante (establecida en 0), c) cambie el multiplicador de la siguiente manera: tome el número de botones + 1, y la parte superior, establecer el multiplicador como buttonCountPlus1:1 y luego buttonCountPlus1:2, y, finalmente, buttonCountPlus1:3. (Explico de dónde obtuve esta fórmula en la respuesta anterior a continuación, si estás interesado).

introduzca la descripción de la imagen aquí

5) Aquí hay una demostración en funcionamiento!

introduzca la descripción de la imagen aquí

Nota: Si sus botones tienen alturas más grandes, entonces tendrá que compensar esto en el valor constante, ya que la restricción es de la parte inferior de la botón.


Respuesta anterior


A pesar de lo que dicen los documentos de Apple y el excelente libro de Erica Sadun (Auto Layout Demystified), es posible espaciar uniformemente las vistas sin espaciadores. Esto es muy simple de hacer en IB y en código para cualquier número de elementos que desee espaciar uniformemente. Todo lo que necesita es una fórmula matemática llamada "fórmula de sección". Es más fácil de hacer que de explicar. Haré lo mejor que pueda demostrándolo en IB, pero es igual de fácil hacer en código.

En el ejemplo en cuestión, usted

1) comience configurando cada etiqueta para que tenga una restricción de centro. Esto es muy fácil de hacer. Simplemente controla el arrastre desde cada etiqueta hasta la parte inferior.

2) Mantenga presionada la tecla mayús, ya que también podría agregar la otra restricción que vamos a usar, a saber, la "guía de diseño de espacio inferior a inferior".

3) Seleccione la "guía de diseño de espacio inferior a inferior" y "centrar horizontalmente en el contenedor". Hacer esto para todos 3 etiqueta.

Mantenga pulsada la tecla mayús para agregar estas dos restricciones para cada etiqueta

Básicamente, si tomamos la etiqueta cuya coordenada deseamos determinar y la dividimos por el número total de etiquetas más 1, entonces tenemos un número que podemos agregar a IB para obtener la ubicación dinámica. Estoy simplificando la fórmula, pero podría usarla para establecer el espaciado horizontal o vertical y horizontal al mismo tiempo. Es super potente!

Aquí están nuestros multiplicadores.

Label1 = 1/4 = .25,

Label2 = 2/4 = .5,

Label3 = 3/4 = .75

(Edit: @ Rivera comentó que usted puede simplemente utilizar las relaciones directamente en el campo multiplicador, y xCode con hacer las matemáticas!)

4) Entonces, seleccionemos Label1 y seleccionemos la restricción inferior. Así: introduzca la descripción de la imagen aquí

5) Seleccione el "Segundo elemento" en el Inspector de Atributos.

6) Desde el menú desplegable, seleccione "Invertir primer y segundo elemento".

7) Cero la constante y el valor hAny wC. (Puede agregar un desplazamiento aquí si lo necesita).

8) Esta es la parte crítica: En el campo multiplicador agregue nuestro primer multiplicador 0.25.

9) Mientras estás en ello, establece el "Primer elemento" superior en "centerY" ya que queremos centrarlo en el centro y de la etiqueta. Así es como debería verse todo eso.

introduzca la descripción de la imagen aquí

10) Repita este proceso para cada etiqueta y conecte el multiplicador relevante: 0.5 para Label2, y 0.75 para Label3. Aquí está el producto final en todas las orientaciones con todos los dispositivos compactos! Súper simple. He estado mirando un montón de soluciones que implican resmas de código, y espaciadores. Esta es, de lejos, la mejor solución que he visto sobre el tema.

Actualización: @kraftydevil agrega que la guía de diseño inferior solo aparece en storyboards, no en xibs. Use 'Bottom Space to Container' en xibs. Buena captura!

introduzca la descripción de la imagen aquí

 301
Author: smileBot,
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-05-11 18:58:23

Solución de creación de interfaces muy rápida:

Para que cualquier número de vistas se espacien uniformemente dentro de una superview, simplemente dé a cada una una restricción de "Alinear Centro X a superview" para el diseño horizontal, o "Alinear Centro Y superview" para el diseño vertical, y establezca el Multiplicador para ser N:p (NOTA: algunos han tenido mejor suerte con p:N - ver más abajo )

Donde

N = total number of views, y

p = position of the view including spaces

La primera posición es 1, luego un espacio, haciendo la siguiente posición 3, por lo que p se convierte en una serie [1,3,5,7,9,...]. Funciona para cualquier número de vistas.

Entonces, si tienes 3 vistas para espaciar, se ve así:

Ilustración de cómo distribuir uniformemente las vistas en IB

EDITAR Nota: La elección de N:p o p:N depende del orden de la relación de su restricción de alineación. Si "Primer Elemento" es Superview.Centro, puede utilizar p:N, mientras que si Superview.El centro es "Segundo elemento", puede usar N:p. En caso de duda, pruebe ambos... :-)

 87
Author: Mete,
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
2016-06-22 09:05:22

A partir de iOS 9, Apple ha hecho esto muy fácil con el (tan esperado) UIStackView. Simplemente seleccione las vistas que desea contener en el Creador de interfaces y elija Editor -> Incrustar en -> Vista de pila. Establezca las restricciones de ancho/alto/margen adecuadas para la vista de pila, y asegúrese de establecer la propiedad de distribución en 'Equal spacing':

Por supuesto, si necesita soportar iOS 8 o inferior, tendrá que elegir una de las otras opciones.

 61
Author: Glorfindel,
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-28 09:12:13

He estado en una montaña rusa de amor autolayout y odiarlo. La clave para amar parece ser aceptar lo siguiente:

  1. La edición del creador de interfaces y la creación automática" útil " de restricciones es casi inútil para todos, excepto para el caso más trivial
  2. Crear categorías para simplificar operaciones comunes es un salvavidas ya que el código es tan repetitivo y detallado.

Dicho esto, lo que está intentando no es sencillo y sería difícil de lograr en interfaz builder. Es bastante simple de hacer en código. Este código, en viewDidLoad, crea y posiciona tres etiquetas como las estás pidiendo:

// Create three labels, turning off the default constraints applied to views created in code
UILabel *label1 = [UILabel new];
label1.translatesAutoresizingMaskIntoConstraints = NO;
label1.text = @"Label 1";

UILabel *label2 = [UILabel new];
label2.translatesAutoresizingMaskIntoConstraints = NO;
label2.text = @"Label 2";

UILabel *label3 = [UILabel new];
label3.translatesAutoresizingMaskIntoConstraints = NO;
label3.text = @"Label 3";

// Add them all to the view
[self.view addSubview:label1];
[self.view addSubview:label2];
[self.view addSubview:label3];

// Center them all horizontally
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

// Center the middle one vertically
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];

// Position the top one half way up
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:0.5 constant:0]];

// Position the bottom one half way down
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:1.5 constant:0]];

Como digo, este código está muy simplificado con un par de métodos de categoría en UIView, pero para mayor claridad he hecho el largo camino aquí.

La categoría es aquí para aquellos interesados, y tiene un método para espaciar uniformemente una matriz de vistas a lo largo de un eje particular.

 51
Author: jrturton,
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-07-29 10:45:07

La mayoría de estas soluciones dependen de que haya un número impar de elementos para que pueda tomar el elemento central y centrarlo. ¿Qué pasa si tiene un número par de artículos que aún desea que se distribuyan uniformemente? Aquí hay una solución más general. Esta categoría distribuirá uniformemente cualquier número de elementos a lo largo del eje vertical u horizontal.

Ejemplo de uso para distribuir verticalmente 4 etiquetas dentro de su vista superior:

[self.view addConstraints:
     [NSLayoutConstraint constraintsForEvenDistributionOfItems:@[label1, label2, label3, label4]
                                        relativeToCenterOfItem:self.view
                                                    vertically:YES]];

NSLayoutConstraint + EvenDistribution.h

@interface NSLayoutConstraint (EvenDistribution)

/**
 * Returns constraints that will cause a set of views to be evenly distributed horizontally
 * or vertically relative to the center of another item. This is used to maintain an even
 * distribution of subviews even when the superview is resized.
 */
+ (NSArray *) constraintsForEvenDistributionOfItems:(NSArray *)views
                             relativeToCenterOfItem:(id)toView
                                         vertically:(BOOL)vertically;

@end

NSLayoutConstraint + EvenDistribution.m

@implementation NSLayoutConstraint (EvenDistribution)

+(NSArray *)constraintsForEvenDistributionOfItems:(NSArray *)views
                           relativeToCenterOfItem:(id)toView vertically:(BOOL)vertically
{
    NSMutableArray *constraints = [NSMutableArray new];
    NSLayoutAttribute attr = vertically ? NSLayoutAttributeCenterY : NSLayoutAttributeCenterX;

    for (NSUInteger i = 0; i < [views count]; i++) {
        id view = views[i];
        CGFloat multiplier = (2*i + 2) / (CGFloat)([views count] + 1);
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view
                                                                      attribute:attr
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:toView
                                                                      attribute:attr
                                                                     multiplier:multiplier
                                                                       constant:0];
        [constraints addObject:constraint];
    }

    return constraints;
}

@end
 20
Author: Ben Dolman,
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-01-28 18:12:28

Echa un vistazo a la biblioteca de código abierto PureLayout. Ofrece algunos métodos de API para distribuir vistas, incluidas variantes donde el espaciado entre cada vista es fijo (el tamaño de la vista varía según sea necesario) y donde el tamaño de cada vista es fijo (el espaciado entre vistas varía según sea necesario). Tenga en cuenta que todos estos se logran sin el uso de cualquier "vistas espaciadoras".

De NSArray+PureLayout.h :

// NSArray+PureLayout.h

// ...

/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. */
- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis
                                alignedTo:(ALAttribute)alignment
                         withFixedSpacing:(CGFloat)spacing;

/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. */
- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis
                                alignedTo:(ALAttribute)alignment
                            withFixedSize:(CGFloat)size;

// ...

Ya que todo es de código abierto, si estás interesado para ver cómo se logra esto sin vistas espaciadoras, solo eche un vistazo a la implementación. (Depende de aprovechar tanto laconstant y multiplier por las limitaciones.)

 16
Author: smileyborg,
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-03-31 15:16:15

La forma correcta y más fácil es usar Vistas de pila.

  1. Agregue sus etiquetas / vistas a la Vista de pila :

introduzca la descripción de la imagen aquí

  1. Seleccione la vista de pila y establezca la distribución como Espaciado igual :

introduzca la descripción de la imagen aquí

  1. Agregar Espaciado al vecino más cercano restricciones a la vista de pila y marcos de actualización:

introduzca la descripción de la imagen aquí

  1. Agregar Altura restricciones a todos las etiquetas:

introduzca la descripción de la imagen aquí

  1. Disfruta de la vista previa:

introduzca la descripción de la imagen aquí

 15
Author: Oleh Kudinov,
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
2016-06-26 22:05:54

Estoy teniendo un problema similar y descubrí este post. Sin embargo, ninguna de las respuestas proporcionadas actualmente resuelve el problema de la manera que desea. No hacen que el espacio sea igual, sino que distribuyen el centro de las etiquetas por igual. Es importante entender que esto no es lo mismo. He construido un pequeño diagrama para ilustrar esto.

Ver Ilustración de Espaciado

Hay 3 vistas, todas de 20pt de altura. El uso de cualquiera de los métodos sugeridos distribuye equitativamente los centros de las vistas y darle el diseño ilustrado. Observe que el centro y de las vistas está espaciado por igual. Sin embargo, el espacio entre la vista superior y la vista superior es de 15pt, mientras que el espacio entre las subviews es de solo 5pt. Para tener las vistas espaciadas por igual, ambas deben ser 10pt, es decir, todas las flechas azules deben ser 10pt.

Sin embargo, todavía no he encontrado una buena solución genérica. Actualmente mi mejor idea es insertar "vistas de espaciado" entre las subvistas y establecer las alturas del espaciado vistas a ser iguales.

 9
Author: Florian,
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-07-31 14:53:08

Pude resolver esto completamente en IB:

  1. Establezca restricciones para alinear el centro Y de cada una de sus subviews con el borde inferior de la superview.
  2. Establezca el multiplicador de cada una de estas restricciones en 1/2n, 3/2n, 5/2n, ..., n-1/2n donde n es el número de subviews que está distribuyendo.

Así que si tiene tres etiquetas, establezca los multiplicadores para cada una de esas restricciones en 0.1666667, 0.5, 0.833333.

 8
Author: hayesk,
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
2016-01-26 19:59:26

Encontré un método perfecto y simple. El diseño automático no le permite cambiar el tamaño de los espacios por igual, pero sí le permite cambiar el tamaño de las vistas por igual. Simplemente coloque algunas vistas invisibles entre sus campos y dígale a auto layout que las mantenga del mismo tamaño. Funciona perfectamente!

XIB inicial

XIB estirado

Una cosa a tener en cuenta, sin embargo, cuando reducía el tamaño en el diseñador de interfaces, a veces se confundía y dejaba una etiqueta donde estaba, y tenía un conflicto si el tamaño era cambiado por una cantidad impar. De lo contrario funcionó perfectamente.

Editar: Descubrí que el conflicto se convirtió en un problema. Debido a eso, tomé una de las restricciones de espaciado, la eliminé y la reemplazé con dos restricciones, una mayor o igual y una menor o igual. Ambas eran del mismo tamaño y tenían una prioridad mucho menor que las otras limitaciones. El resultado fue que no hubo más conflictos.

 5
Author: Owen Godfrey,
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-11-02 10:12:27
 3
Author: Mehul Thakkar,
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
2014-01-02 04:38:19

Con etiquetas esto funciona bien al menos:

@"H:|-15-[first(==second)]-[second(==third)]-[third(==first)]-15-|

Si el primero tiene el mismo ancho que el segundo, y el segundo el tercero, y el tercero el primero, entonces todos obtendrán el mismo ancho... Puedes hacerlo tanto horizontalmente (H) como verticalmente (V).

 3
Author: Johannes,
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-03-19 12:21:23

Basándose en la respuesta de Ben Dolman, esto distribuye las vistas de manera más uniforme (con relleno, etc.):

+(NSArray *)constraintsForEvenDistributionOfItems:(NSArray *)views
                           relativeToCenterOfItem:(id)toView vertically:(BOOL)vertically
{
    NSMutableArray *constraints = [NSMutableArray new];
    NSLayoutAttribute attr = vertically ? NSLayoutAttributeCenterY : NSLayoutAttributeCenterX;

    CGFloat min = 0.25;
    CGFloat max = 1.75;
    CGFloat d = (max-min) / ([views count] - 1);
    for (NSUInteger i = 0; i < [views count]; i++) {
        id view = views[i];
        CGFloat multiplier = i * d + min;
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view
                                                                      attribute:attr
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:toView
                                                                      attribute:attr
                                                                     multiplier:multiplier
                                                                       constant:0];
        [constraints addObject:constraint];
    }

    return constraints;
}
 3
Author: Ray W,
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-06-29 21:06:50

Sé que ha pasado un tiempo desde la primera respuesta, pero me encontré con el mismo problema y quiero compartir mi solución. Para las generaciones venideras...

Establezco mis puntos de vista en viewDidLoad:

- (void)viewDidLoad {

    [super viewDidLoad];

    cancelButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
    [cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
    [self.view addSubview:cancelButton];

    middleButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    middleButton.translatesAutoresizingMaskIntoConstraints = NO;
    [middleButton setTitle:@"Middle" forState:UIControlStateNormal];
    [self.view addSubview:middleButton];

    nextButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    nextButton.translatesAutoresizingMaskIntoConstraints = NO;
    [nextButton setTitle:@"Next" forState:UIControlStateNormal];
    [self.view addSubview:nextButton];


    [self.view setNeedsUpdateConstraints];

}

Y luego, en updateViewConstrains, primero elimino todas las restricciones, luego creo el diccionario de vistas y luego calculo el espacio que se utilizará entre las vistas. Después de eso, solo uso el Formato de Lenguaje Visual para establecer las restricciones:

- (void)updateViewConstraints {


    [super updateViewConstraints];

    [self.view removeConstraints:self.view.constraints];

    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(cancelButton, nextButton, middleButton);

    float distance=(self.view.bounds.size.width-cancelButton.intrinsicContentSize.width-nextButton.intrinsicContentSize.width-middleButton.intrinsicContentSize.width-20-20)/  ([viewsDictionary count]-1);  // 2 times 20 counts for the left & rigth margins
    NSNumber *distancies=[NSNumber numberWithFloat:distance];

//    NSLog(@"Distancies: %@", distancies);
//    
//    NSLog(@"View Width: %f", self.view.bounds.size.width);
//    NSLog(@"Cancel Width: %f", cancelButton.intrinsicContentSize.width);
//    NSLog(@"Middle Width: %f", middleButton.intrinsicContentSize.width);
//    NSLog(@"Next Width: %f", nextButton.intrinsicContentSize.width);



    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-[cancelButton]-dis-[middleButton]-dis-[nextButton]-|"
                                                                   options:NSLayoutFormatAlignAllBaseline
                                                                   metrics:@{@"dis":distancies}
                                                                     views:viewsDictionary];


    [self.view addConstraints:constraints];



    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[nextButton]-|"
                                                          options:0
                                                          metrics:nil
                                                            views:viewsDictionary];
    [self.view addConstraints:constraints];



}

Lo bueno de esto el método es que tienes que hacer muy pocas matemáticas. No estoy diciendo que esta sea la solución perfecta, pero trabajo para el diseño que estaba tratando de lograr.

Espero que ayude.

 2
Author: Marcal,
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-01-21 19:53:59

Aquí hay una solución que centrará verticalmente cualquier número de subviews, incluso si tienen tamaños únicos. Lo que quieres hacer es hacer un contenedor de nivel medio, centrarlo en el superview, luego poner todas las subviews en el contenedor y ordenarlas entre sí. Pero también es crucial que los restrinja a la parte superior y inferior del contenedor, para que el contenedor pueda tener el tamaño correcto y estar centrado en la vista superior. Calculando la altura correcta de sus subviews, el contenedor puede estar centrado verticalmente.

En este ejemplo, self es la supervisión en la que está centrando todas las subviews.

NSArray *subviews = @[ (your subviews in top-to-bottom order) ];

UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
container.translatesAutoresizingMaskIntoConstraints = NO;
for (UIView *subview in subviews) {
    subview.translatesAutoresizingMaskIntoConstraints = NO;
    [container addSubview:subview];
}
[self addSubview:container];

[self addConstraint:[NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
                                                    toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                    toItem:self attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:container attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual
                                                    toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]];

if (0 < subviews.count) {
    UIView *firstSubview = subviews[0];
    [container addConstraint:[NSLayoutConstraint constraintWithItem:firstSubview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                             toItem:container attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];
    UIView *lastSubview = subviews.lastObject;
    [container addConstraint:[NSLayoutConstraint constraintWithItem:lastSubview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                                             toItem:container attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]];

    UIView *subviewAbove = nil;
    for (UIView *subview in subviews) {
        [container addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
                                                                 toItem:container attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f]];
        if (subviewAbove) {
            [container addConstraint:[NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                     toItem:subviewAbove attribute:NSLayoutAttributeBottom multiplier:1.0f constant:10.0f]];
        }
        subviewAbove = subview;
    }
}
 2
Author: Kevin Conner,
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-18 18:22:59

Acabo de resolver mi problema usando la función multiplicador. No estoy seguro de que funcione para todos los casos, pero para mí funcionó perfectamente. Estoy en Xcode 6.3 para tu información.

Lo que terminé haciendo fue:

1) Primero colocar mis botones en una pantalla de 320px de ancho distribuido de la manera que quería que se vea en un dispositivo de 320px.

paso 1: colocar los botones

2) Luego agregué una restricción de espacio inicial a superview en todos mis botones.

paso 2: añadir restricciones de espacio

3) Luego modifiqué las propiedades de el espacio inicial para que la constante sea 0 y el multiplicador sea el desplazamiento x dividido por el ancho de la pantalla (por ejemplo, mi primer botón era 8px desde el borde izquierdo, así que establecí mi multiplicador en 8/320)

4) Entonces el paso importante aquí es cambiar el segundo Elemento en la relación de restricción para que sea la superview.Trailing en lugar de supervision.principal. Esto es clave porque superview.Delante es 0 y detrás en mi caso es 320, por lo que 8/320 es 8 px en un dispositivo de 320px, entonces cuando cambia el ancho de la superview a 640 o lo que sea, todas las vistas se mueven en una proporción relativa al ancho del tamaño de pantalla de 320px. La matemática aquí es mucho más simple de entender.

paso 3 y 4: cambie el multiplicador a xPos / screenWidth y establezca el segundo elemento en .Trailing

 2
Author: ucangetit,
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-03 04:30:45

Muchas respuestas no son correctas, pero obtienen muchos conteos. Aquí solo escribo una solución programáticamente, las tres vistas se alinean horizontalmente, sin usar vistas espaciadoras, pero solo funcionan cuando se conocen los anchos de las etiquetas cuando se usan en storyboard.

NSDictionary *views = NSDictionaryOfVariableBindings(_redView, _yellowView, _blueView);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|->=0-[_redView(40)]->=0-[_yellowView(40)]->=0-[_blueView(40)]->=0-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:nil views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_redView(60)]" options:0 metrics:nil views:views]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_redView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_redView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeLeading multiplier:0.5 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_blueView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeLeading multiplier:1.5 constant:40]];
 2
Author: zgjie,
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-16 09:31:55

Aquí hay otra respuesta. Yo estaba respondiendo una pregunta similar y vi enlace hace referencia a esta pregunta. No vi ninguna respuesta similar a la mía. Así que pensé en escribirlo aquí.

  class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.whiteColor()
        setupViews()
    }

    var constraints: [NSLayoutConstraint] = []

    func setupViews() {

        let container1 = createButtonContainer(withButtonTitle: "Button 1")
        let container2 = createButtonContainer(withButtonTitle: "Button 2")
        let container3 = createButtonContainer(withButtonTitle: "Button 3")
        let container4 = createButtonContainer(withButtonTitle: "Button 4")

        view.addSubview(container1)
        view.addSubview(container2)
        view.addSubview(container3)
        view.addSubview(container4)

        [

            // left right alignment
            container1.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: 20),
            container1.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -20),
            container2.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
            container2.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),
            container3.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
            container3.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),
            container4.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
            container4.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),


            // place containers one after another vertically
            container1.topAnchor.constraintEqualToAnchor(view.topAnchor),
            container2.topAnchor.constraintEqualToAnchor(container1.bottomAnchor),
            container3.topAnchor.constraintEqualToAnchor(container2.bottomAnchor),
            container4.topAnchor.constraintEqualToAnchor(container3.bottomAnchor),
            container4.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),


            // container height constraints
            container2.heightAnchor.constraintEqualToAnchor(container1.heightAnchor),
            container3.heightAnchor.constraintEqualToAnchor(container1.heightAnchor),
            container4.heightAnchor.constraintEqualToAnchor(container1.heightAnchor)
            ]
            .forEach { $0.active = true }
    }


    func createButtonContainer(withButtonTitle title: String) -> UIView {
        let view = UIView(frame: .zero)
        view.translatesAutoresizingMaskIntoConstraints = false

        let button = UIButton(type: .System)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle(title, forState: .Normal)
        view.addSubview(button)

        [button.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor),
            button.leftAnchor.constraintEqualToAnchor(view.leftAnchor),
            button.rightAnchor.constraintEqualToAnchor(view.rightAnchor)].forEach { $0.active = true }

        return view
    }
}

introduzca la descripción de la imagen aquí

Y de nuevo, esto se puede hacer bastante fácilmente con iOS9 UIStackViews también.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.greenColor()
        setupViews()
    }

    var constraints: [NSLayoutConstraint] = []

    func setupViews() {

        let container1 = createButtonContainer(withButtonTitle: "Button 1")
        let container2 = createButtonContainer(withButtonTitle: "Button 2")
        let container3 = createButtonContainer(withButtonTitle: "Button 3")
        let container4 = createButtonContainer(withButtonTitle: "Button 4")

        let stackView = UIStackView(arrangedSubviews: [container1, container2, container3, container4])
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .Vertical
        stackView.distribution = .FillEqually
        view.addSubview(stackView)

        [stackView.topAnchor.constraintEqualToAnchor(view.topAnchor),
            stackView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),
            stackView.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: 20),
            stackView.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -20)].forEach { $0.active = true }
    }


    func createButtonContainer(withButtonTitle title: String) -> UIView {
        let button = UIButton(type: .Custom)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = UIColor.redColor()
        button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
        button.setTitle(title, forState: .Normal)
        let buttonContainer = UIStackView(arrangedSubviews: [button])
        buttonContainer.distribution = .EqualCentering
        buttonContainer.alignment = .Center
        buttonContainer.translatesAutoresizingMaskIntoConstraints = false
        return buttonContainer
    }
}

Observe que es exactamente el mismo enfoque que el anterior. Agrega cuatro vistas de contenedor que se llenan por igual y se agrega una vista a cada vista de pila que está alineada en el centro. Pero, esta versión de UIStackView reduce algo de código y se ve bien.

 2
Author: Sandeep,
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
2016-04-19 17:37:15

Swift 3 version

let _redView = UIView()
        _redView.backgroundColor = UIColor.red
        _redView.translatesAutoresizingMaskIntoConstraints = false

        let _yellowView = UIView()
        _yellowView.backgroundColor = UIColor.yellow
        _yellowView.translatesAutoresizingMaskIntoConstraints = false

        let _blueView = UIView()
        _blueView.backgroundColor = UIColor.blue
        _blueView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(_redView)
        self.view.addSubview(_yellowView)
        self.view.addSubview(_blueView)

        var views = ["_redView": _redView, "_yellowView": _yellowView, "_blueView":_blueView]

        var nslayoutConstraint_H = NSLayoutConstraint.constraints(withVisualFormat: "|->=0-[_redView(40)]->=0-[_yellowView(40)]->=0-[_blueView(40)]->=0-|", options: [.alignAllTop, .alignAllBottom], metrics: nil, views: views)
        self.view.addConstraints(nslayoutConstraint_H)

        var nslayoutConstraint_V = NSLayoutConstraint.constraints(withVisualFormat: "V:[_redView(60)]", options: NSLayoutFormatOptions.init(rawValue: 0), metrics: nil, views: views)
        self.view.addConstraints(nslayoutConstraint_V)


        let constraint_red = NSLayoutConstraint.init(item: self.view, attribute: .centerY, relatedBy: .equal, toItem: _redView, attribute: .centerY, multiplier: 1, constant: 0)
        self.view.addConstraint(constraint_red)

        let constraint_yellow = NSLayoutConstraint.init(item: self.view, attribute: .centerX, relatedBy: .equal, toItem: _yellowView, attribute: .centerX, multiplier: 1, constant: 0)
        self.view.addConstraint(constraint_yellow)

        let constraint_yellow1 = NSLayoutConstraint.init(item: _redView, attribute: .centerX, relatedBy: .equal, toItem: _yellowView, attribute: .leading, multiplier: 0.5, constant: 0)
        self.view.addConstraint(constraint_yellow1)

        let constraint_yellow2 = NSLayoutConstraint.init(item: _blueView, attribute: .centerX, relatedBy: .equal, toItem: _yellowView, attribute: .leading, multiplier: 1.5, constant: 40)
        self.view.addConstraint(constraint_yellow2)
 2
Author: Sarath Raveendran,
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
2016-10-24 06:39:17

Otro enfoque podría ser que las etiquetas superior e inferior tengan restricciones relativas a la vista superior e inferior, respectivamente, y que la vista central tenga restricciones superiores e inferiores relativas a la primera y tercera vista, respectivamente.

Tenga en cuenta que tiene más control sobre las restricciones de lo que podría parecer al arrastrar las vistas una cerca de la otra hasta que aparezcan líneas discontinuas de guía; estas indican restricciones entre los dos objetos que se formarán en lugar de entre el objeto y el superview.

En este caso, entonces querrá alterar las restricciones para que sean "Mayores o iguales a" el valor deseado, en lugar de "iguales a" para permitirles cambiar el tamaño. No estoy seguro de si esto hará exactamente lo que quieres.

 1
Author: Colin,
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
2012-11-05 22:11:13

Una forma muy fácil de resolver esto en InterfaceBuilder:

Establezca la etiqueta centrada (label2) en "Centro Horizontal en Contenedor" y "Centro Vertical en Contenedor"

Seleccione la etiqueta centrada y la etiqueta superior (label1 + label2) y agregue DOS restricciones para el Espaciado Vertical. Unocon Mayor o Igual el espaciado mínimo. Uno con Menor o Igual el espaciado máximo.

Lo mismo para la etiqueta centrada y la etiqueta inferior (label2 + label3).

Además, también puede agregar dos restricciones a label1 - Espacio Superior a SuperView y dos restricciones a label2 - Espacio Inferior A SuperView.

El resultado será que los 4 espaciamientos cambiarán sus tamaños por igual.

 1
Author: sust86,
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-01-24 17:35:37

He hecho una función que podría ayudar. Este ejemplo de uso :

 [self.view addConstraints: [NSLayoutConstraint fluidConstraintWithItems:NSDictionaryOfVariableBindings(button1, button2, button3)
                                                                asString:@[@"button1", @"button2", @"button3"]
                                                               alignAxis:@"V"
                                                          verticalMargin:100
                                                        horizontalMargin:50
                                                             innerMargin:25]];

Causará que distribución vertical (lo sentimos, no tienen la reputación de 10 para incrustar imágenes). Y si cambia el eje y algunos valores de margen :

alignAxis:@"H"
verticalMargin:120
horizontalMargin:20
innerMargin:10

Obtendrás esa distribución horizontal.

Soy novato en iOS, pero voilà !

EvenDistribution.h

@interface NSLayoutConstraint (EvenDistribution)

/**
 * Returns constraints that will cause a set of subviews
 * to be evenly distributed along an axis.
 */
+ (NSArray *)  fluidConstraintWithItems:(NSDictionary *) views
                               asString:(NSArray *) stringViews
                              alignAxis:(NSString *) axis
                         verticalMargin:(NSUInteger) vMargin
                       horizontalMargin:(NSUInteger) hMargin
                            innerMargin:(NSUInteger) inner;
@end

EvenDistribution.m

#import "EvenDistribution.h"

@implementation NSLayoutConstraint (EvenDistribution)

+ (NSArray *) fluidConstraintWithItems:(NSDictionary *) dictViews
                              asString:(NSArray *) stringViews
                             alignAxis:(NSString *) axis
                        verticalMargin:(NSUInteger) vMargin
                      horizontalMargin:(NSUInteger) hMargin
                           innerMargin:(NSUInteger) iMargin

{
    NSMutableArray *constraints = [NSMutableArray arrayWithCapacity: dictViews.count];
    NSMutableString *globalFormat = [NSMutableString stringWithFormat:@"%@:|-%d-",
                                     axis,
                                     [axis isEqualToString:@"V"] ? vMargin : hMargin
                                     ];



        for (NSUInteger i = 0; i < dictViews.count; i++) {

            if (i == 0)
                [globalFormat appendString:[NSString stringWithFormat: @"[%@]-%d-", stringViews[i], iMargin]];
            else if(i == dictViews.count - 1)
                [globalFormat appendString:[NSString stringWithFormat: @"[%@(==%@)]-", stringViews[i], stringViews[i-1]]];
            else
               [globalFormat appendString:[NSString stringWithFormat: @"[%@(==%@)]-%d-", stringViews[i], stringViews[i-1], iMargin]];

            NSString *localFormat = [NSString stringWithFormat: @"%@:|-%d-[%@]-%d-|",
                                     [axis isEqualToString:@"V"] ? @"H" : @"V",
                                     [axis isEqualToString:@"V"] ? hMargin : vMargin,
                                     stringViews[i],
                                     [axis isEqualToString:@"V"] ? hMargin : vMargin];

            [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:localFormat
                                                                                     options:0
                                                                                     metrics:nil
                                                                                       views:dictViews]];


    }
    [globalFormat appendString:[NSString stringWithFormat:@"%d-|",
                                [axis isEqualToString:@"V"] ? vMargin : hMargin
                                ]];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:globalFormat
                                                                             options:0
                                                                             metrics:nil
                                                                               views:dictViews]];

    return constraints;

}

@end
 1
Author: penumbra,
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-03-18 09:00:47

Sí, puede hacer esto únicamente en interface builder y sin escribir código - la única advertencia es que está redimensionando la etiqueta en lugar de distribuir espacios en blanco. En este caso, alinee la X e Y de la etiqueta 2 con la superview para que quede fija en el centro. Luego establezca el espacio vertical de la etiqueta 1 en la vista superior y para etiquetar 2 en el estándar, repita para la etiqueta 3. Después de establecer la etiqueta 2, la forma más fácil de establecer la etiqueta 1 y 3 es redimensionarlas hasta que se ajusten.

Aquí está la visualización horizontal, tenga en cuenta que el espacio vertical entre la etiqueta 1 y 2 se establece en estándar:pantalla horizontal

Y aquí está la versión vertical: introduzca la descripción de la imagen aquí

Me doy cuenta de que no están absolutamente 100% espaciados equitativamente entre las líneas de base debido a la diferencia entre el espacio estándar entre las etiquetas y el espacio estándar para la superview. Si eso le molesta, establezca el tamaño en 0 en lugar de estándar

 1
Author: James,
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-04-17 15:30:43

Establezco un valor de ancho solo para el primer elemento (>= a width) y una distancia mínima entre cada elemento (>= a distance). Luego uso Ctrl para arrastrar segundo, tercero... elemento en el primero para encadenar dependencias entre los elementos.

introduzca la descripción de la imagen aquí

 1
Author: Vladimír Slavík,
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-06-07 21:18:36

Llego tarde a la fiesta pero tengo una solución de trabajo para crear un menú horizontalmente con espaciado. Se puede hacer fácilmente usando == en NSLayoutConstraint

const float MENU_HEIGHT = 40;

- (UIView*) createMenuWithLabels: (NSArray *) labels
    // labels is NSArray of NSString
    UIView * backgroundView = [[UIView alloc]init];
    backgroundView.translatesAutoresizingMaskIntoConstraints = false;

    NSMutableDictionary * views = [[NSMutableDictionary alloc] init];
    NSMutableString * format = [[NSMutableString alloc] initWithString: @"H:|"];
    NSString * firstLabelKey;

    for(NSString * str in labels)
    {
        UILabel * label = [[UILabel alloc] init];
        label.translatesAutoresizingMaskIntoConstraints = false;
        label.text = str;
        label.textAlignment = NSTextAlignmentCenter;
        label.textColor = [UIColor whiteColor];
        [backgroundView addSubview: label];
        [label fixHeightToTopBounds: MENU_HEIGHT-2];
        [backgroundView addConstraints: [label fixHeightToTopBounds: MENU_HEIGHT]];
        NSString * key = [self camelCaseFromString: str];
        [views setObject: label forKey: key];
        if(firstLabelKey == nil)
        {
            [format appendString: [NSString stringWithFormat: @"[%@]", key]];
            firstLabelKey = key;
        }
        else
        {
            [format appendString: [NSString stringWithFormat: @"[%@(==%@)]", key, firstLabelKey]];
        }
    }

    [format appendString: @"|"];

    NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat: (NSString *) format
                                                                               options: 0
                                                                               metrics: nil
                                                                                 views: (NSDictionary *) views];
    [backgroundView addConstraints: constraints];
    return backgroundView;
}
 1
Author: tsuz,
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
2016-04-13 11:50:03

¿Por qué no crea una vista de tabla y crea isScrollEnabled = false

 0
Author: Josh O'Connor,
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-05 18:37:08