ios objective-c uiview autolayout cgsize

ios - Uso correcto de intrinsicContentSize y sizeThatFits: en UIView Subclass con autolayout



objective-c cgsize (1)

No creo que necesites definir un intrinsicContentSize.

Aquí hay dos razones para pensar que:

  1. Cuando la documentación de Auto Layout analiza intrinsicContentSize , se refiere a ella como relevante para las "vistas en hoja" como botones o etiquetas donde un tamaño puede calcularse únicamente en función de su contenido. La idea es que son las hojas en el árbol de jerarquía de vistas, no ramas, porque no están compuestas de otras vistas.

  2. IntrinsicContentSize no es realmente un concepto "fundamental" en Auto Layout. Los conceptos fundamentales son solo restricciones y los atributos limitados por restricciones. El tamaño del contenido intrínseco, las prioridades de contenido y las prioridades de resistencia a la compresión son realmente conveniencias para generar restricciones internas relacionadas con el tamaño. El tamaño final es solo el resultado de esas restricciones que interactúan con todas las demás restricciones de la manera habitual.

¿Y qué? Entonces, si su "vista personalizada" es en realidad solo un conjunto de un par de otras vistas, entonces no necesita definir un tamaño de contenido intrínseco. Simplemente puede definir las restricciones que crean el diseño que desea, y esas restricciones también producirán el tamaño que desea.

En el caso particular que describe, establecería una restricción de espacio inferior>> 0 desde la etiqueta a la vista de supervisión, otra desde la imagen a la vista de supervisión, y luego también una restricción de baja prioridad de altura cero para la vista como una todo. La restricción de prioridad baja intentará reducir el tamaño del ensamblaje, mientras que las otras restricciones evitan que se reduzca tanto que recorta sus subvistas.

Si nunca define explícitamente intrinsicContentSize, ¿cómo ve el tamaño resultante de estas restricciones? Una forma es forzar el diseño y luego observar los resultados.

Otra forma es usar systemLayoutSizeFittingSize: (y en iOS8, el sistema poco anunciado systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: . Este es un primo más cercano a sizeThatFits: que intrinsicContentSize . Es lo que el sistema utilizará para calcular el tamaño apropiado de su vista, teniendo en cuenta todas las restricciones que contiene, incluidas las restricciones de tamaño del contenido intrínseco, así como todas las demás.

Desafortunadamente, si tiene una etiqueta multilínea, es probable que también tenga que configurar el preferredMaxLayoutWidth para obtener un buen resultado, pero esa es otra historia ...

Hago esta pregunta simple (de alguna manera) solo para ser delicado, porque a veces me preocupa el uso indebido que pueda estar haciendo de muchas API de UIView, especialmente cuando se trata de la reproducción automática.

Para hacerlo más simple, seguiré con un ejemplo, supongamos que necesito una subclase UIView que tenga un icono de imagen y una etiqueta multilínea; El comportamiento que quiero es que la altura de mi vista cambie con la altura de la etiqueta (para que se ajuste al texto interior), además, lo estoy distribuyendo con el generador de Interfaz, así que tengo algo como esto:

con algunas restricciones que dan un ancho y una altura fijos a la vista de la imagen, y un ancho y una posición fijos (en relación con la vista de la imagen) a la etiqueta:

Ahora, si configuro un texto para la etiqueta, quiero que la vista cambie de tamaño en altura para que se ajuste correctamente, o que permanezca con la misma altura que tiene en la xib. Antes de autolayout hubiera hecho siempre algo como esto:

En el archivo de subclases de CustoView, habría reemplazado sizeThatFits: así:

- (CGSize) sizeThatFits:(CGSize)size{ //this stands for whichever method I would have used //to calculate the height needed to display the text based on the font CGSize labelSize = [self.titleLabel intrinsicContentSize]; //check if we''re bigger than what''s in ib, otherwise resize CGFloat newHeight = (labelSize.height <= 21) ? 51: labelSize.height+20; size.height = newHeight; return size; }

Y de lo que hubiera llamado algo así:

myView.titleLabel.text = @"a big text to display that should be more than a line"; [myView sizeToFit];

Ahora, pensando en restricciones, sé que los sistemas de autolayout llaman intrinsicContentSize en los elementos del árbol de vista para saber cuál es su tamaño y hacer sus cálculos, por lo tanto, debería reemplazar intrinsicContentSize en mi subvista para devolver exactamente lo mismo que devuelve en el método sizeThatFits: mostrado anteriormente, excepto por el hecho de que, anteriormente, al llamar a sizeToFit , mi vista se redimensionó correctamente, pero ahora con autolayout, en combinación con un xib, esto no va a suceder.

Por supuesto, podría estar llamando a sizeToFit cada vez que edite texto en mi subclase, junto con un tamaño de sizeThatFits: intrinsicContentSize anulado que devuelve el mismo tamaño de sizeThatFits: pero de alguna manera no creo que esta sea la forma correcta de hacerlo.

Estaba pensando en anular needsUpdateConstraints y updateConstraints , pero aún así no tiene mucho sentido, ya que el ancho y el alto de mi vista se deducen y se traducen de la máscara de tamaño automático del xib.

Por mucho tiempo, ¿cuál crees que es la forma más limpia y correcta de hacer exactamente lo que muestro aquí y de que sea totalmente automático?