Autolayout: haga que la altura de la vista sea relativa a la mitad de la altura de la supervista

136

He estado entrando en autolayouts recientemente y estoy atascado en lo que parece un ejemplo de problema realmente trivial. Tengo una vista que quiero sentarme en la parte superior de la pantalla y ocupar la mitad de la altura de la pantalla. Simple antes de la distribución automática: simplemente colóquelo en su lugar y dígale que se expanda verticalmente cuando la supervista cambie de tamaño.

Ahora, por mi vida no puedo ver cómo hacerlo. Esto es lo que obtengo cuando intento configurar esto:

blues de autolayout

La restricción de espacio inferior se establece en "igual a 284", lo cual es absoluto y absolutamente inútil para mí cuando cambio al diseño de iPhone4, ya que mantiene 284 puntos de espacio en la parte inferior de la pantalla y reduce la vista para que ya no sea la mitad. Tamaño de la pantalla. Y no hay forma de establecer esa restricción para que sea igual a una fracción de la altura de cualquier otra vista ...

Después de luchar por un tiempo, la única forma en que puedo pensar en hacer esto sería introducir otra vista debajo de esta vista, fijar sus alturas por igual, hacer que se sienten uno encima del otro y luego establecer la segunda vista (inferior) para que sea invisible .. que parece un poco feo!

¿Me estoy perdiendo algo obvio? ..

Asignar
fuente
1
No creo que sea feo, pero es un truco inteligente para obtener lo que quieres usando IB. He hecho esto, y cuando usas nombres de elementos adecuados, puedes aclarar lo que está sucediendo. Incluso puede tener un tercer elemento en una posición diferente, o centros, cambiar el tamaño en función de estas dos subvistas.
Jelle

Respuestas:

167

Esto ahora es posible en IB a partir de [al menos] Xcode 5.1.1. Aunque me llevó algún tiempo descubrir que en realidad es súper simple:

Primero cree una restricción de alineación superior básica (también deberá configurar las restricciones inferior, izquierda y derecha, como es normal). Luego seleccione la restricción y navegue al inspector de atributos :

Demostración de los pasos anteriores.

Entonces puedes ajustar el multiplicador. Si lo desea, déjelo en el 50% de la súper vista 1, ya que está alineado por el centro de la súper. Esta también es una excelente manera de crear vistas que también son otros porcentajes (como el 25% de la super vista)

Demostración del segundo paso anterior

Firo
fuente
nice :) Creo que esta publicación debe marcarse como respuesta aceptada :) El desarrollador de iOS a menudo prefiere la solución Interface Builder en lugar de la solución de código
hqt
@hqt, gracias. Creo que cuando se escribió la respuesta aceptada, este método no estaba disponible. A veces, los que preguntan no vuelven a consultar las preguntas anteriores ni se preocupan por cambiar la respuesta aceptada. Pero en última instancia, solo estoy aquí para ayudar, ¡me alegro de que lo haya hecho!
Firo
3
Estoy un poco confundido. Intenté esto pero solo centra la vista en la supervista, no ajusta la altura de la vista.
Dean el
@Dean, es necesario asegurarse de que el First Itemes View.Topno View.Center Y. De lo contrario, sí, solo lo centrará. También deberá asegurarse de que otras restricciones estén establecidas correctamente para manejar los otros bordes de la vista.
Firo el
1
View.Top es igual a Superview.Center Y multiplicador 1 no le da altura. Esta respuesta es incompleta. ¡Todo lo que tienes que hacer es pensar en lo que estás diciendo y puedes ver que te da una línea en el centro! Editaría esta respuesta para aclarar de qué otras restricciones estás hablando.
smileBot
184

Solución de guión gráfico donde puede establecer la proporción exacta entre las vistas

Establecer restricción de igualdad de altura

Ahora:

Editar el multiplicador de la restricción

¡¡¡LUCRO!!!

Resultado

PD También tenga en cuenta que este método funciona con vistas en diferentes niveles de anidación y (obviamente) aplicable para el ancho

PPS a veces puede ser útil "invertir el primer y segundo elemento" de la restricción o establecer un multiplicador inverso (por ejemplo, 2 en lugar de 0.5) (pero estos métodos no son útiles si no comprende cómo se relacionan las vistas entre sí).

Fyodor Volchyok
fuente
1
El paso 2 no parece funcionar para mí. No puedo seleccionar nada en el panel excepto alternar 'Restricción al margen'. Estoy tratando de establecer el ancho de un UIImageView en un UITableViewCell al 50% de la vista de contenido.
DrMickeyLauer
2
ACTUALIZACIÓN: Obviamente, el generador de interfaces no permite que la vista de contenido sea el objetivo explícito de ninguna restricción de diseño automático. Tengo que insertar una subvista ficticia como elemento secundario de la vista de contenido para que esto funcione.
DrMickeyLauer
1
Esto funciona para mi. Debe seleccionar las dos vistas en la lista, no la pantalla del generador. para porcentajes, divida la vista más pequeña por la vista más grande para obtener el valor del multiplicador, por ejemplo, vista más pequeña 25, vista más grande 135 - 25/135 = 0.185. Establecer esto como el valor del multiplicador para obtener una vista que al x1 y x2 = 25, pero con mayor escala hasta 6 y 6 y etc
latenitecoder
1
Esto funcionó para mí, pero tenga en cuenta que también tuve que agregar tres restricciones que establecieron las restricciones de margen de la subvista en 0. Gracias
raddevus
Esta debería ser la respuesta aceptada. Primero trato de aceptar la respuesta. No funcionó, luego me desplacé hacia abajo y vi esta respuesta y funcionó. ¡Gracias!
Mihir Oza
31

Después de un poco más de tiempo, se me ocurrió lo siguiente.

Lo estoy señalando como una respuesta, pero no es muy satisfactorio, ya que supone que en realidad no puede hacer esto en Interface Builder, pero la restricción correcta se puede agregar en el código después como:

- (void) viewWillAppear:(BOOL)animated
{

    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:upperview
                                                                 attribute:NSLayoutAttributeHeight 
                                                                 relatedBy:0 
                                                                    toItem:self.view
                                                                 attribute:NSLayoutAttributeHeight
                                                                multiplier:.5 
                                                                  constant:0];
    [self.view addConstraint:constraint];

}

Básicamente, establece un multiplicador de 0.5 contra la altura de self.view, actuando en la vista superior. Tuve que establecer la prioridad de la restricción de espacio vertical inferior en IB a menos de 1000 para evitar un montón de mensajes de tiempo de ejecución sobre romper las restricciones también.

Entonces, si alguien puede mostrar cómo hacer esto en Interface Builder, eso respondería mejor a mi pregunta, de lo contrario, ¿supongo que esto es tan bueno (por ahora)?

Asignar
fuente
3
Creo que esto es tan bueno como se pone ahora. Sería bueno que Apple nos diera acceso al valor del multiplicador en IB, de modo que se pudiera establecer así como la constante.
rdelmar
3
Para cualquiera que esté mirando esta respuesta, Xcode 5.1 ahora le permite configurar el multiplicador a través de Interface Builder. Ahora puedo configurar vistas que son la mitad de la altura de su supervista todo a través de IB.
Mark Krenek
9

Un poco más fácil y directo que el método que la respuesta de Fyodor Volchyok. - Mantenga presionado el botón de control y haga clic en la subvista. -Todavía manteniendo presionado el botón de comando, arrastre el cursor a la supervista y luego haga clic en la supervista. -Seleccione "Relación de aspecto".

ingrese la descripción de la imagen aquí

-A continuación, haga clic en el Inspector de tamaño. -Luego haga doble clic en la restricción. ingrese la descripción de la imagen aquí

-Asegúrese de que esté seleccionada la "altura" para ambos elementos. ingrese la descripción de la imagen aquí

-Entonces cambie el "Multiplicador" a 0.5 para la mitad de la pantalla, o cualquier fracción de la supervista que desee. ingrese la descripción de la imagen aquí

usuario444333222
fuente
Enfoque fácil y rápido! Gracias amigo
Abdullah Saeed
7

También hay otra posibilidad en el código en caso de que tenga 2 vistas que tengan la misma altura: simplemente configure la altura de view2 en la altura de view1 (el truco aquí no es establecer la altura de view1 explícitamente).

    [self.view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:[topLayoutGuide]-0-[_view1]-0-[_view2(==_view1)]-0-[bottomLayoutGuide]"
                            options:0
                            metrics:nil
                              views:viewsDict]];
brainray
fuente
No me di cuenta de que podría hacer referencia a otras vistas para anchos / alturas como esas. Esta es la respuesta más clara de la OMI si ya está en el lenguaje de formato visual.
loeschg
El ejemplo de @brainray también se explica en developer.apple.com aquí
alecs.popa
0

Versión rápida de la respuesta de Mete:

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.



    upperView.translatesAutoresizingMaskIntoConstraints = false


    var constraint = NSLayoutConstraint(item: upperView,
                                        attribute: NSLayoutAttribute.top,
                                        relatedBy: NSLayoutRelation.equal,
                                        toItem: self.view,
                                        attribute: NSLayoutAttribute.top,
                                        multiplier: 1,
                                        constant: 0)

    self.view.addConstraint(constraint)


    constraint = NSLayoutConstraint(item: upperView,
                                    attribute: NSLayoutAttribute.height,
                                    relatedBy: NSLayoutRelation.equal,
                                    toItem: self.view,
                                    attribute: NSLayoutAttribute.height,
                                    multiplier: 0.5,
                                    constant: 0)

    self.view.addConstraint(constraint)


    constraint = NSLayoutConstraint(item: upperView,
                                    attribute: NSLayoutAttribute.leading,
                                    relatedBy: NSLayoutRelation.equal,
                                    toItem: self.view,
                                    attribute: NSLayoutAttribute.leading,
                                    multiplier: 1,
                                    constant: 0)

    self.view.addConstraint(constraint)


    constraint = NSLayoutConstraint(item: upperView,
                                    attribute: NSLayoutAttribute.trailing,
                                    relatedBy: NSLayoutRelation.equal,
                                    toItem: self.view,
                                    attribute: NSLayoutAttribute.trailing,
                                    multiplier: 1,
                                    constant: 0)

    self.view.addConstraint(constraint)


}
usuario444333222
fuente