cambiar el tamaño de la supervista después de que las subvistas cambien dinámicamente usando el diseño automático

83

No puedo, por el amor de Dios, el truco de esta supervista de cambio de tamaño.

Tengo una UIView *superview con 4 UILabels. 2 funcionan como encabezado para los otros 2.

El contenido de los 4 son dinámicos provenientes de la base de datos.

SizeToFitvs SizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, pasando ya sea UILayoutFittingCompressedSizeo UILayoutFittingExpandedSize.

Utilizo el diseño automático mediante programación y he configurado la altura de la supervista para que sea igual o mayor a un número ficticio.

dónde y cómo uso estos SizeToFitvs sizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, pasando ya sea UILayoutFittingCompressedSizeoUILayoutFittingExpandedSize . He leído muchos consejos aquí en la pila pero terminé sin nada.

DEBO volver a calcular las restricciones para la supervista en algún lugar específico. ¿Puede establecer la altura en ´ @ property` en su clase de controlador y eliminarla y leerla? Atm he intentado poner todo en todas partes y algo más. Aún así, obtengo el resultado final del mismo tamaño con la altura ficticia y el texto flotando afuera. Incluso después de configurar clipsToBound en subview.

Me estoy rascando el pelo de .. ayuda

Pedroinpaz
fuente
1
Oye, ¿podrías publicar tu código en algún lugar de pastebin o algo si pudiera echar un vistazo? Sufro de un problema similar. Ha pasado una semana o más.
esh

Respuestas:

104

Si está utilizando Diseño automático, esto es lo que debe hacer:

  1. Asegúrese de no agregar restricciones fijas de ancho y / o alto a ninguna de sus subvistas (según las dimensiones que desee dimensionar dinámicamente). La idea es permitir que el tamaño del contenido intrínseco de cada subvista determine la altura de la subvista.UILabels vienen con 4 restricciones implícitas automáticas que intentarán (con menos de la prioridad Requerida) mantener el marco de la etiqueta en el tamaño exacto requerido para que quepa todo el texto dentro.

  2. Asegúrese de que los bordes de cada etiqueta estén conectados rígidamente (con las restricciones de prioridad requeridas) a los bordes entre sí y a su supervista. Desea asegurarse de que si imagina que una de las etiquetas aumenta de tamaño, esto obligaría a las otras etiquetas a dejar espacio para ella y, lo que es más importante, obligaría a la supervista a expandirse también.

  3. Solo agregue restricciones a la supervista para establecer su posición, no el tamaño (al menos, no para las dimensiones que desea que se dimensionen dinámicamente). Recuerde que si configura correctamente las restricciones internas, su tamaño estará determinado por los tamaños de todas las subvistas, ya que sus bordes están conectados a los de ellos de alguna manera.

Eso es. No necesita llamar sizeToFito systemLayoutSizeFittingSize:hacer que esto funcione, simplemente cargue sus vistas y configure el texto y eso debería ser todo. El motor de diseño del sistema hará los cálculos para que usted resuelva sus limitaciones. (En todo caso, es posible que deba llamar setNeedsLayouta la supervista ... pero esto no debería ser necesario).

smileyborg
fuente
Gracias smileyborg. Una respuesta tardía ya que estaba en medio de un proyecto y no obtuve lo que mencionaste. Ahora he tenido la oportunidad de trabajar un poco más con restricciones programáticas y especialmente con, constraintsWithVisualFormaty entiendo totalmente su punto sobre las subvistas que contienen, estirando y empujando la supervista a su tamaño :) Gracias de nuevo
Pedroinpeace
Estoy de acuerdo con la solución, pero no funciona para mí, consulte stackoverflow.com/questions/34635838/…
Omer
Esta respuesta es mágica. Mucho menos esfuerzo de mi parte para que las vistas se vean bien.
Chris
1
Debe mencionarse que debe configurar translatesAutoresizingMaskIntoConstraints = NOsi está usando xib.
KudoCC
translatesAutoresizingMaskIntoConstraints = NO es la respuesta para mi caso. Pero ahora la vista del contenedor perdió el marco y su origen es siempre (0,0), no puedo ponerlo en el lugar que deseo. stackoverflow.com/questions/45548372/…
karim
24

Usar vistas de contenedor

En el siguiente ejemplo, tengo una imagen de 30x30 y UILabeles más pequeña que la vista que contiene el texto del marcador de posición. Necesitaba que la vista contenedora fuera al menos tan grande como la imagen, pero necesitaba crecer para contener texto de varias líneas.

En formato visual, el contenedor interno se ve así:

H:|-(15.0)-[image(30.0)]-(15.0)-[label]-(15.0)-|
V:|[image(30.0)]|
V:|[label(>=30.0)]|

Luego, configure la vista contenedora para que coincida con la altura de la etiqueta. Ahora la vista contenedora se ajustará al tamaño de la etiqueta.

Como @smileyborg señaló en su respuesta, conectar el contenido de manera rígida a la supervista informa al motor de diseño que la vista de contenedor simple debería hacer que crezca.

Rectángulos de alineación amarillos

Si desea que los rectángulos de alineación amarillos agreguen -UIViewShowAlignmentRects YESen la lista de argumentos de ejecución de su esquema.

UILabel que es multilínea

Cameron Lowell Palmer
fuente
12
-UIViewShowAlignmentRects YES- ¡gran consejo!
Ralfonso
2
En este caso, el contenedor solo tiene que adaptar su altura a la etiqueta. ¿Y si el contenedor se adaptara a la suma de las alturas de más de una vista?
da Rocha Pires
7

Esto se hizo mucho más fácil con la introducción de Stack Views en iOS 9. Use una vista de pila dentro de su vista para contener todo su contenido que cambia de tamaño, y luego simplemente llame

view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
view.setNeedsLayout()
view.layoutIfNeeded()

después de cambiar su contenido. Entonces puede obtener su nueva talla llamando

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

si alguna vez necesita calcular el tamaño exacto requerido para una vista.

Jacob Ruth
fuente
2
Estoy usando StackView y agregando vistas dinámicamente, estas vistas no están cambiando de tamaño. @ JacobRuth
Mansuu ....
6

Esto casi sigue la respuesta de @smileyborg y viene con un ejemplo concreto.

ingrese la descripción de la imagen aquí

No describirá todas las restricciones, sino las relacionadas con el cálculo de la altura de los objetos de la interfaz de usuario.

  1. [Etiqueta] Las etiquetas no deben tener una heightrestricción fija , en este caso, AutoLayout no cambiará el tamaño de las etiquetas para que se ajusten al texto, por lo que establecer restricciones de borde es la clave. (flechas verdes)
  2. [Subvista] Los pasos 1 y 3 son muy fáciles de seguir, pero este paso puede malinterpretarse. Como en el caso de las etiquetas, las subvistas no deben tener heightrestricciones establecidas. Todas las subvistas deben tener un topconjunto de restricciones, ignorando la bottomrestricción, lo que puede hacerle pensar que desencadenará una excepción de restricción insatisfecha en tiempo de ejecución, pero no lo hará si establece una bottomrestricción para la última subvista. No hacerlo arruinará el diseño. (flechas rojas)

  3. [Supervista] Establezca todas las restricciones de la forma que necesite, pero preste mucha atención a las heightrestricciones. Asígnele un valor aleatorio, pero hágalo opcional, AutoLayout establecerá la altura exactamente para adaptarse a las subvistas. (flechas azules)

Esto funciona perfectamente, no es necesario llamar a ningún método adicional de actualización del diseño del sistema.

Stefan
fuente
cómo hacer que una altura sea opcional ... Soy nuevo en iOS, así que no puedo resolverlo.Gracias
Faisal Naseer