¿Cómo se usa el diseño automático dentro de UITableViewCell
s en una vista de tabla para permitir que el contenido y las subvistas de cada celda determinen la altura de la fila (en sí / automáticamente), mientras se mantiene un rendimiento de desplazamiento suave?
ios
uitableview
autolayout
nsautolayout
row-height
smileyborg
fuente
fuente
contentSize
y cómopreferredMaxLayoutWidth
funciona. Ver aquí . Dicho esto, si configura sus restricciones correctamente, entonces no debería necesitarpreferredMaxLayoutWidth
y, de hecho, puede crear resultados inesperados.Respuestas:
TL; DR: ¿No te gusta leer? Vaya directamente a los proyectos de muestra en GitHub:
Descripción conceptual
Los primeros 2 pasos a continuación son aplicables independientemente de las versiones de iOS que esté desarrollando.
1. Configurar y agregar restricciones
En su
UITableViewCell
subclase, agregue restricciones para que las subvistas de la celda tengan sus bordes fijados en los bordes de contentView de la celda (lo más importante en los bordes superior e inferior). NOTA: no ancle subvistas a la celda misma; solo a la celdacontentView
! Deje que el tamaño de contenido intrínseco de estas subvistas controle la altura de la vista de contenido de la celda de la vista de tabla asegurándose de que la resistencia de compresión de contenido y las restricciones de abrazo de contenido en la dimensión vertical para cada subvista no se anulen por las restricciones de mayor prioridad que ha agregado. ( ¿Eh? Haz clic aquí. )Recuerde, la idea es tener las subvistas de la celda conectadas verticalmente a la vista de contenido de la celda para que puedan "ejercer presión" y hacer que la vista de contenido se expanda para adaptarse a ellas. Usando una celda de ejemplo con algunas subvistas, aquí hay una ilustración visual de cómo deberían verse algunas (¡no todas!) De sus restricciones:
Puede imaginar que a medida que se agregue más texto a la etiqueta del cuerpo de varias líneas en la celda de ejemplo anterior, tendrá que crecer verticalmente para ajustarse al texto, lo que forzará efectivamente que la celda crezca en altura. (¡Por supuesto, debe obtener las restricciones correctas para que esto funcione correctamente!)
Definir correctamente sus restricciones es definitivamente la parte más difícil y más importante para obtener alturas de celda dinámicas trabajando con Auto Layout. Si comete un error aquí, podría evitar que todo lo demás funcione, ¡así que tómese su tiempo! Recomiendo configurar sus restricciones en el código porque sabe exactamente qué restricciones se agregan y dónde, y es mucho más fácil depurar cuando las cosas salen mal. Agregar restricciones en el código puede ser tan fácil y significativamente más poderoso que Interface Builder que utiliza anclas de diseño o una de las fantásticas API de código abierto disponibles en GitHub.
updateConstraints
método de su subclase UITableViewCell. Tenga en cuenta queupdateConstraints
se puede llamar más de una vez, por lo que para evitar agregar las mismas restricciones más de una vez, asegúrese de ajustar el código de adición de restricciones dentroupdateConstraints
de un cheque para una propiedad booleana comodidSetupConstraints
(que establece en SÍ después de ejecutar su restricción -adición de código una vez). Por otro lado, si tiene un código que actualiza las restricciones existentes (como ajustar laconstant
propiedad en algunas restricciones), colóquelo dentroupdateConstraints
pero fuera de la verificación paradidSetupConstraints
que pueda ejecutarse cada vez que se llame al método.2. Determine los identificadores únicos de reutilización de celdas de vista de tabla
Para cada conjunto único de restricciones en la celda, use un identificador de reutilización de celda único. En otras palabras, si sus celdas tienen más de un diseño único, cada diseño único debe recibir su propio identificador de reutilización. (Un buen indicio de que necesita usar un nuevo identificador de reutilización es cuando la variante de celda tiene un número diferente de subvistas, o las subvistas se organizan de manera distinta).
Por ejemplo, si estaba mostrando un mensaje de correo electrónico en cada celda, podría tener 4 diseños únicos: mensajes con solo un asunto, mensajes con un asunto y un cuerpo, mensajes con un asunto y un archivo adjunto de foto, y mensajes con un asunto, cuerpo y adjunto de foto. Cada diseño tiene restricciones completamente diferentes necesarias para lograrlo, por lo que una vez que se inicializa la celda y se agregan las restricciones para uno de estos tipos de celda, la celda debe obtener un identificador de reutilización único específico para ese tipo de celda. Esto significa que cuando retira una celda para su reutilización, las restricciones ya se han agregado y están listas para ese tipo de celda.
Tenga en cuenta que debido a las diferencias en el tamaño del contenido intrínseco, ¡las celdas con las mismas restricciones (tipo) aún pueden tener alturas variables! No confunda diseños fundamentalmente diferentes (diferentes restricciones) con diferentes marcos de vista calculados (resueltos a partir de restricciones idénticas) debido a diferentes tamaños de contenido.
Para iOS 8: celdas de tamaño automático
3. Habilite la estimación de altura de fila
Con iOS 8, Apple ha internalizado gran parte del trabajo que antes tenía que implementar antes de iOS 8. Para permitir que funcione el mecanismo de celda de tamaño automático, primero debe establecer la
rowHeight
propiedad en la vista de tabla a la constanteUITableViewAutomaticDimension
. Luego, simplemente necesita habilitar la estimación de altura de fila configurando laestimatedRowHeight
propiedad de la vista de tabla en un valor distinto de cero, por ejemplo:Lo que esto hace es proporcionar a la vista de tabla una estimación temporal / marcador de posición para las alturas de fila de las celdas que aún no están en pantalla. Luego, cuando estas celdas estén a punto de desplazarse en la pantalla, se calculará la altura real de la fila. Para determinar la altura real de cada fila, la vista de tabla pregunta automáticamente a cada celda qué altura
contentView
debe basarse en el ancho fijo conocido de la vista de contenido (que se basa en el ancho de la vista de tabla, menos cualquier elemento adicional como un índice de sección o vista de accesorios) y las restricciones de diseño automático que ha agregado a la vista de contenido y subvistas de la celda. Una vez que se ha determinado esta altura real de la celda, la altura estimada anterior para la fila se actualiza con la nueva altura real (y cualquier ajuste al contenido de la vista de tabla contentSize / contentOffset se realiza según sea necesario).En términos generales, la estimación que proporciona no tiene que ser muy precisa: solo se usa para dimensionar correctamente el indicador de desplazamiento en la vista de tabla, y la vista de tabla hace un buen trabajo al ajustar el indicador de desplazamiento para estimaciones incorrectas como usted Desplazar celdas en pantalla. Debe establecer la
estimatedRowHeight
propiedad en la vista de tabla (enviewDidLoad
o similar) a un valor constante que sea el alto de fila "promedio". Solo si las alturas de sus filas tienen una variabilidad extrema (por ejemplo, difieren en un orden de magnitud) y nota que el indicador de desplazamiento "salta" a medida que se desplaza, debe molestarse en implementartableView:estimatedHeightForRowAtIndexPath:
para hacer el cálculo mínimo requerido para devolver una estimación más precisa para cada fila.Para soporte de iOS 7 (implementando el dimensionamiento automático de la celda usted mismo)
3. Haga un pase de diseño y obtenga la altura de la celda
Primero, cree una instancia fuera de pantalla de una celda de vista de tabla, una instancia para cada identificador de reutilización , que se usa estrictamente para los cálculos de altura. (Fuera de la
tableView:cellForRowAtIndexPath:
pantalla, lo que significa que la referencia de celda se almacena en una propiedad / ivar en el controlador de vista y nunca se devuelve para que la vista de tabla se muestre en la pantalla). A continuación, la celda se debe configurar con el contenido exacto (por ejemplo, texto, imágenes, etc.) que se mantendría si se mostrara en la vista de tabla.Luego, fuerce a la celda a diseñar inmediatamente sus subvistas, y luego use el
systemLayoutSizeFittingSize:
método en laUITableViewCell
'scontentView
para averiguar cuál es la altura requerida de la celda. ÚseloUILayoutFittingCompressedSize
para obtener el tamaño más pequeño requerido para adaptarse a todos los contenidos de la celda. La altura puede ser devuelta desde eltableView:heightForRowAtIndexPath:
método delegado.4. Use las alturas de fila estimadas
Si la vista de la tabla tiene más de un par de docenas de filas, descubrirá que al hacer la resolución de restricciones de Diseño automático puede atascarse rápidamente el subproceso principal cuando se carga por primera vez la vista de la tabla, como
tableView:heightForRowAtIndexPath:
se llama en cada fila en la primera carga ( para calcular el tamaño del indicador de desplazamiento).A partir de iOS 7, puede (y absolutamente debe) usar la
estimatedRowHeight
propiedad en la vista de tabla. Lo que esto hace es proporcionar a la vista de tabla una estimación temporal / marcador de posición para las alturas de fila de las celdas que aún no están en pantalla. Luego, cuando estas celdas están a punto de desplazarse en la pantalla, se calculará la altura real de la fila (llamandotableView:heightForRowAtIndexPath:
) y la altura estimada se actualizará con la real.En términos generales, la estimación que proporciona no tiene que ser muy precisa: solo se usa para dimensionar correctamente el indicador de desplazamiento en la vista de tabla, y la vista de tabla hace un buen trabajo al ajustar el indicador de desplazamiento para estimaciones incorrectas como usted Desplazar celdas en pantalla. Debe establecer la
estimatedRowHeight
propiedad en la vista de tabla (enviewDidLoad
o similar) a un valor constante que sea el alto de fila "promedio". Solo si las alturas de sus filas tienen una variabilidad extrema (por ejemplo, difieren en un orden de magnitud) y nota que el indicador de desplazamiento "salta" a medida que se desplaza, debe molestarse en implementartableView:estimatedHeightForRowAtIndexPath:
para hacer el cálculo mínimo requerido para devolver una estimación más precisa para cada fila.5. (Si es necesario) Agregue el almacenamiento en caché de altura de fila
Si ha hecho todo lo anterior y todavía encuentra que el rendimiento es inaceptablemente lento cuando se resuelve la restricción
tableView:heightForRowAtIndexPath:
, desafortunadamente deberá implementar un almacenamiento en caché para las alturas de las celdas. (Este es el enfoque sugerido por los ingenieros de Apple.) La idea general es dejar que el motor de Autolayout resuelva las restricciones la primera vez, luego almacene en caché la altura calculada para esa celda y use el valor en caché para todas las solicitudes futuras para la altura de esa celda. El truco, por supuesto, es asegurarse de borrar la altura en caché de una celda cuando ocurra algo que pueda hacer que cambie la altura de la celda; principalmente, esto será cuando cambie el contenido de esa celda o cuando ocurran otros eventos importantes (como el ajuste del usuario el control deslizante de tamaño de texto de tipo dinámico).Código de muestra genérico de iOS 7 (con muchos comentarios jugosos)
Proyectos de muestra
Estos proyectos son ejemplos totalmente funcionales de vistas de tabla con alturas de fila variables debido a las celdas de vista de tabla que contienen contenido dinámico en UILabels.
Xamarin (C # / .NET)
Si está utilizando Xamarin, consulte este proyecto de muestra elaborado por @KentBoogaart .
fuente
heightForRowAtIndexPath
, mantener la celda y devolverla la próxima vez quecellForRowAtIndexPath
se llame.iOS8
Todavía se recomienda la implementacióniOS9
yiOS10
, o hay nuevos enfoques desde que se publicó esta respuesta?Para iOS 8 anterior es realmente simple:
o
Pero para iOS 7, la clave es calcular la altura después de la distribución automática:
Importante
Si hay etiquetas de varias líneas, no olvides configurarlo
numberOfLines
en0
.No olvides
label.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)
El código de ejemplo completo está aquí .
fuente
Ejemplo rápido de una altura variable UITableViewCell
Actualizado para Swift 3
La respuesta rápida de William Hu es buena, pero me ayuda a tener algunos pasos simples pero detallados al aprender a hacer algo por primera vez. El siguiente ejemplo es mi proyecto de prueba mientras aprendía a hacer una
UITableView
altura de celda variable. Lo basé en este ejemplo básico UITableView para Swift .El proyecto terminado debería verse así:
Crea un nuevo proyecto
Puede ser solo una aplicación de vista única.
Agrega el código
Agregue un nuevo archivo Swift a su proyecto. Llámalo MyCustomCell. Esta clase mantendrá los puntos de venta de las vistas que agregue a su celda en el guión gráfico. En este ejemplo básico solo tendremos una etiqueta en cada celda.
Conectaremos esta salida más tarde.
Abra ViewController.swift y asegúrese de tener el siguiente contenido:
Nota IMPORTANTE:
Son las siguientes dos líneas de código (junto con el diseño automático) las que hacen posible la altura de celda variable:
Configurar el guión gráfico
Agregue una vista de tabla a su controlador de vista y use el diseño automático para fijarlo a los cuatro lados. Luego arrastre una celda de vista de tabla a la vista de tabla. Y en la celda Prototipo, arrastre una Etiqueta. Use el diseño automático para anclar la etiqueta a los cuatro bordes de la vista de contenido de la Celda de vista de tabla.
Nota IMPORTANTE:
Otras configuraciones de IB
Nombre de clase personalizado e identificador
Seleccione la celda de vista de tabla y configure la clase personalizada como
MyCustomCell
(el nombre de la clase en el archivo Swift que agregamos). También establezca el Identificador para que seacell
(la misma cadena que usamos para elcellReuseIdentifier
en el código anterior.Líneas cero para etiqueta
Establezca el número de líneas
0
en su etiqueta. Esto significa varias líneas y permite que la etiqueta se redimensione en función de su contenido.Conecta los enchufes
tableView
variable en elViewController
código.myCellLabel
variable en laMyCustomCell
clase.Terminado
Debería poder ejecutar su proyecto ahora y obtener celdas con alturas variables.
Notas
Si no está fijando los bordes iniciales y finales (izquierdo y derecho), también puede necesitar configurar las etiquetas
preferredMaxLayoutWidth
para que sepa cuándo ajustar la línea. Por ejemplo, si ha agregado una restricción Centro horizontalmente a la etiqueta en el proyecto anterior en lugar de fijar los bordes inicial y final, entonces necesitaría agregar esta línea altableView:cellForRowAtIndexPath
método:Ver también
fuente
preferredMaxLayoutWidth
contra la celdacontentSize
? De esa manera, si tiene un accesorioView o se deslizó para editar, ¿aún se lo tendrá en cuenta?Envolví la solución iOS7 de @ smileyborg en una categoría
Decidí incluir esta solución inteligente de @smileyborg en una
UICollectionViewCell+AutoLayoutDynamicHeightCalculation
categoría.La categoría también rectifica los problemas descritos en la respuesta de @ wildmonkey (cargar una celda desde una punta y
systemLayoutSizeFittingSize:
regresarCGRectZero
)No tiene en cuenta ningún almacenamiento en caché, pero se adapta a mis necesidades en este momento. Siéntase libre de copiar, pegar y hackearlo.
UICollectionViewCell + AutoLayoutDynamicHeightCalculation.h
UICollectionViewCell + AutoLayoutDynamicHeightCalculation.m
Ejemplo de uso:
Afortunadamente no tendremos que hacer este jazz en iOS8, ¡pero ahí está por ahora!
fuente
[YourCell new]
y usar eso como el muñeco. Siempre que el código de construcción del código de restricción se active en su instancia, y active un pase de diseño mediante programación, debería estar listo.UICollectionViews
.Aquí está mi solución:
Usted necesita decirle a la
TableView
delestimatedHeight
antes de cargar la vista. De lo contrario, no podrá comportarse como se esperaba.C objetivo
Actualización a Swift 4.2
fuente
estimatedRowHeight
varía fila por fila? ¿Debo sobre o subestimar? uso mínimo o máximo de la altura que usotableView
?estimatedRowHeight
, afecta principalmente el tamaño de la barra de desplazamiento, nunca la altura de las celdas reales. Sea audaz en la altura que elija: afectará la animación de inserción / eliminación.La solución propuesta por @smileyborg es casi perfecta. Si tiene una celda personalizada y desea una o más
UILabel
con alturas dinámicas, entonces el método systemLayoutSizeFittingSize combinado con AutoLayout habilitado devuelve aCGSizeZero
menos que mueva todas las restricciones de la celda de la celda a su contentView (como lo sugiere @TomSwift aquí Cómo cambiar el tamaño de la supervista a ¿se ajusta a todas las subvistas con autolayout? ).Para hacerlo, debe insertar el siguiente código en su implementación personalizada UITableViewCell (gracias a @Adrian).
Mezclar la respuesta de @smileyborg con esto debería funcionar.
fuente
systemLayoutSizeFittingSize
necesita ser llamado en contentView, no celularUn problema bastante importante que acabo de encontrar para publicar como respuesta.
La respuesta de @ smileyborg es mayormente correcta. Sin embargo, si tiene algún código en el
layoutSubviews
método de su clase de celda personalizada, por ejemplo, configurandopreferredMaxLayoutWidth
, entonces no se ejecutará con este código:Me confundió por un tiempo. Entonces me di cuenta de que es porque esos solo están activando las Subvistas de diseño en
contentView
la celda, no en la misma.Mi código de trabajo se ve así:
Tenga en cuenta que si está creando una nueva celda, estoy bastante seguro de que no necesita llamar
setNeedsLayout
ya que ya debería estar configurada. En los casos en que guarde una referencia a una celda, probablemente debería llamarla. De cualquier manera, no debería doler nada.Otro consejo si está utilizando subclases de celda donde está configurando cosas como
preferredMaxLayoutWidth
. Como @smileyborg menciona, "la celda de la vista de la tabla aún no tiene su ancho fijado al ancho de la vista de la tabla". Esto es cierto, y es un problema si está haciendo su trabajo en su subclase y no en el controlador de vista. Sin embargo, simplemente puede establecer el marco de la celda en este punto utilizando el ancho de la tabla:Por ejemplo en el cálculo de altura:
(Resulta que guardo en caché esta celda particular para su reutilización, pero eso es irrelevante).
fuente
En caso de que la gente todavía tenga problemas con esto. Escribí una publicación rápida en el blog sobre el uso de Autolayout con UITableViews Aprovechando Autolayout para Dynamic Cell Heights , así como un componente de código abierto para ayudar a hacer esto más abstracto y más fácil de implementar. https://github.com/Raizlabs/RZCellSizeManager
fuente
Siempre que su diseño en su celda sea bueno.
Actualización: debe usar el cambio de tamaño dinámico introducido en iOS 8.
fuente
tableView:cellForRowAtIndexPath:
en eltableView:heightForRowAtIndexPath:
momento?systemLayoutSizeFittingSize:
entableView:cellForRowAtIndexPath:
caché el resultado y luego lo usotableView:heightForRowAtIndexPath:
, funciona bien siempre y cuando las restricciones estén configuradas correctamente, por supuesto.(para Xcode 8.x / Xcode 9.x leído en la parte inferior)
Tenga cuidado con el siguiente problema en Xcode 7.x, que puede ser una fuente de confusión:
Interface Builder no maneja la configuración de celda de dimensionamiento automático correctamente. Incluso si sus restricciones son absolutamente válidas, IB seguirá quejándose y le dará sugerencias y errores confusos. La razón es que IB no está dispuesto a cambiar la altura de la fila según lo dicten sus restricciones (de modo que la celda se ajuste a su contenido). En cambio, mantiene fija la altura de la fila y comienza a sugerirle que cambie sus restricciones, lo que debe ignorar .
Por ejemplo, imagine que ha configurado todo bien, sin advertencias, sin errores, todo funciona.
Ahora, si cambia el tamaño de fuente (en este ejemplo, estoy cambiando el tamaño de fuente de la etiqueta de descripción de 17.0 a 18.0).
Debido a que el tamaño de la fuente aumentó, la etiqueta ahora quiere ocupar 3 filas (antes de eso ocupaba 2 filas).
Si Interface Builder funcionara como se esperaba, cambiaría el tamaño de la altura de la celda para acomodar la nueva altura de la etiqueta. Sin embargo, lo que realmente sucede es que IB muestra el ícono rojo de error de diseño automático y sugiere que modifique las prioridades de abrazo / compresión.
Debe ignorar estas advertencias. En cambio, lo que puede * hacer es cambiar manualmente la altura de la fila (seleccione Celda> Inspector de tamaño> Altura de fila).
¡Estaba cambiando esta altura un clic a la vez (usando el paso hacia arriba / abajo) hasta que desaparecen los errores de la flecha roja! (en realidad, recibirá advertencias amarillas, en cuyo punto simplemente continúe y haga 'marcos de actualización', todo debería funcionar).
* Tenga en cuenta que en realidad no tiene que resolver estos errores rojos o advertencias amarillas en Interface Builder: en tiempo de ejecución, todo funcionará correctamente (incluso si IB muestra errores / advertencias). Solo asegúrese de que en el tiempo de ejecución en el registro de la consola no obtenga ningún error de AutoLayout.
De hecho, tratar de actualizar siempre la altura de la fila en IB es súper molesto y, a veces, casi imposible (debido a los valores fraccionarios).
Para evitar las molestas advertencias / errores de IB, puede seleccionar las vistas involucradas y elegir
Size Inspector
la propiedadAmbiguity
Verify Position Only
Xcode 8.x / Xcode 9.x parece (a veces) estar haciendo las cosas de manera diferente a Xcode 7.x, pero aún de manera incorrecta. Por ejemplo, incluso cuando
compression resistance priority
/hugging priority
se establece en requerido (1000), Interface Builder podría estirar o recortar una etiqueta para que se ajuste a la celda (en lugar de cambiar el tamaño de la altura de la celda para que se ajuste a la etiqueta). Y en tal caso, es posible que ni siquiera muestre advertencias o errores de AutoLayout. O a veces hace exactamente lo que hizo Xcode 7.x, descrito anteriormente.fuente
Para establecer la dimensión automática para la altura de la fila y la altura estimada de la fila, asegúrese de seguir los siguientes pasos para que la dimensión automática sea efectiva para el diseño de altura de celda / fila.
UITableViewAutomaticDimension
a rowHeight & estimadoRowHeightheightForRowAt
y devolverle un valorUITableViewAutomaticDimension
)-
C objetivo:
Rápido:
Para instancia de etiqueta en UITableviewCell
Nota : Si tiene más de una etiqueta (UIElements) con longitud dinámica, que debe ajustarse de acuerdo con su tamaño de contenido: Ajuste 'Prioridad de contenido y resistencia a la compresión' para las etiquetas que desea expandir / comprimir con mayor prioridad.
fuente
tableView: heightForRow
fuente de datos.tableView: heightForRow
. (para iOS 10-tableView: heightForRow
se requiere)tableView: heightForRow
..if (indexPath.row == 0) { return 100} else { return UITableView.automaticDimension }
Al igual que @ Bob-Spryn, me encontré con un problema bastante importante que estoy publicando como respuesta.
Luché con @ smileyborg de respuesta por un tiempo. El Gotcha que me encontré es que si usted ha definido su celular prototipo en IB con elementos adicionales (
UILabels
,UIButtons
, etc.) en IB cuando se instancia la celda con [[YourTableViewCellClass alloc] init]
no va a crear una instancia de todos los otros elementos dentro de esa célula a menos que haya código escrito para hacer eso. (Tuve una experiencia similar coninitWithStyle
).Para que el guión gráfico cree una instancia de todos los elementos adicionales con los que obtiene su celda
[tableView dequeueReusableCellWithIdentifier:@"DoseNeeded"]
(No,[tableView dequeueReusableCellWithIdentifier:forIndexPath:]
ya que esto causará problemas interesantes). Cuando haga esto, se instanciarán todos los elementos que definió en IB.fuente
Vista de tabla dinámica Altura de celda y diseño automático
Una buena manera de resolver el problema con el diseño automático del guión gráfico:
fuente
fuente
Otra "solución": omita toda esta frustración y use un UIScrollView en su lugar para obtener un resultado que se vea y se sienta idéntico a UITableView.
Esa fue la "solución" dolorosa para mí, después de haber pasado literalmente más de 20 horas muy frustrantes en total tratando de construir algo como lo que smileyborg sugirió y fallando durante muchos meses y tres versiones de lanzamientos de App Store.
Mi opinión es que si realmente necesita soporte para iOS 7 (para nosotros, es esencial), entonces la tecnología es demasiado frágil y lo intentará. Y ese UITableView es completamente excesivo en general, a menos que esté utilizando algunas de las funciones avanzadas de edición de filas y / o realmente necesite admitir más de 1000 "filas" (en nuestra aplicación, en realidad nunca es más de 20 filas).
La ventaja adicional es que el código se vuelve increíblemente simple en comparación con toda la basura delegada y viceversa que viene con UITableView. Es solo un bucle de código en viewOnLoad que se ve elegante y es fácil de administrar.
Aquí hay algunos consejos sobre cómo hacerlo:
Usando Storyboard o un archivo plumín, cree un ViewController y una vista raíz asociada.
Arrastre sobre UIScrollView a su vista raíz.
Agregue restricciones arriba, abajo, izquierda y derecha a la vista de nivel superior para que UIScrollView llene toda la vista raíz.
Agregue un UIView dentro del UIScrollView y llámelo "contenedor". Agregue restricciones superiores, inferiores, izquierda y derecha a UIScrollView (su elemento primario). TRUCO CLAVE: Agregue también restricciones de "Anchos iguales" para vincular UIScrollView y UIView.
NOTA: Recibirá un error "la vista de desplazamiento tiene una altura de contenido desplazable ambigua" y que su UIView de contenedor debe tener una altura de 0 píxeles. Ninguno de los errores parece importar cuando la aplicación se está ejecutando.
Cree archivos de plumín y controladores para cada una de sus "celdas". Use UIView no UITableViewCell.
En su ViewController raíz, esencialmente agrega todas las "filas" al contenedor UIView y agrega restricciones mediante programación que vinculan sus bordes izquierdo y derecho a la vista del contenedor, sus bordes superiores a la vista superior del contenedor (para el primer elemento) o al anterior célula. Luego, vincule la celda final con el fondo del contenedor.
Para nosotros, cada "fila" está en un archivo plumín. Entonces el código se ve así:
Y aquí está el código para UITools.addViewToTop:
El único "problema" que he encontrado con este enfoque hasta ahora es que UITableView tiene una buena característica de encabezados de sección "flotantes" en la parte superior de la vista a medida que se desplaza. La solución anterior no hará eso a menos que agregue más programación, pero para nuestro caso particular, esta característica no era 100% esencial y nadie se dio cuenta cuando desapareció.
Si desea divisores entre sus celdas, simplemente agregue una vista UIV de 1 píxel de alto en la parte inferior de su "celda" personalizada que se parece a un divisor.
Asegúrese de activar "rebotes" y "rebotar verticalmente" para que funcione el control de actualización y que parezca más una vista de tabla.
TableView muestra algunas filas y divisores vacíos debajo de su contenido, si no llena la pantalla completa donde esta solución no lo hace. Pero personalmente, prefiero que las filas vacías no estuvieran allí de todos modos, con una altura de celda variable siempre me pareció "defectuoso" tener las filas vacías allí.
Espero que algún otro programador lea mi publicación ANTES de perder más de 20 horas tratando de resolverlo con Table View en su propia aplicación. :)
fuente
Tuve que usar vistas dinámicas (vistas de configuración y restricciones por código) y cuando quise establecer el ancho de la etiqueta PreferredMaxLayoutWidth fue 0. Así que tengo una altura de celda incorrecta.
Entonces agregué
antes de ejecutar
Después de que el ancho de la etiqueta era el esperado y la altura dinámica se calculaba correctamente.
fuente
Supongamos que tiene una celda con una subvista y desea que la altura de la celda sea lo suficientemente alta como para abarcar la subvista + relleno.
1) Establezca la restricción inferior de la subvista igual a cell.contentView menos el relleno que desea. No establezca restricciones en la celda o cell.contentView en sí.
2) Establezca la
rowHeight
propiedad tableView otableView:heightForRowAtIndexPath:
enUITableViewAutomaticDimension
.3) Establezca la
estimatedRowHeight
propiedad de tableView otableView:estimatedHeightForRowAtIndexPath:
adivine mejor la altura.Eso es.
fuente
Si realiza el diseño mediante programación, esto es lo que debe tener en cuenta para iOS 10 utilizando anclajes en Swift.
Hay tres reglas / pasos
NÚMERO 1: establezca estas dos propiedades de tableview en viewDidLoad, la primera le dice a la tableview que debe esperar tamaños dinámicos en sus celdas, la segunda es solo para permitir que la aplicación calcule el tamaño del indicador de la barra de desplazamiento, por lo que ayuda para actuación.
NÚMERO 2: es importante que necesite agregar las subvistas al contentView de la celda, no a la vista, y también usar su guía de diseño de diseños para anclar las subvistas en la parte superior e inferior, este es un ejemplo práctico de cómo hacerlo.
Cree un método que agregue las subvistas y realice el diseño, llámelo en el método init.
NÚMERO 3: NO LLAME AL MÉTODO:
Si lo hace, anulará su implementación.
Siga estas 3 reglas para celdas dinámicas en vistas de tabla.
Aquí hay una implementación de trabajo https://github.com/jamesrochabrun/MinimalViewController
fuente
Si tienes una cuerda larga . por ejemplo, uno que no tiene un salto de línea. Entonces usted podría encontrarse con algunos problemas.
La solución "supuesta" se menciona en la respuesta aceptada y en algunas otras respuestas. Solo necesitas agregar
Encuentro la respuesta de Suragh la más completa y concisa , por lo tanto, no es confusa.
Aunque no explican por qué son necesarios estos cambios. Vamos a hacer eso.
Suelta el siguiente código en un proyecto.
Tenga en cuenta que no he agregado ninguna restricción de tamaño . Solo he agregado restricciones centerX, centerY. Pero aún así la etiqueta tendrá el tamaño correcto ¿Por qué?
Debido a
contentSize
.Para procesar esto mejor, primero mantenga el paso 0, luego comente los pasos 1-6. Dejate
setupLayout()
quedar. Observa el comportamiento.Luego, descomente el paso 1 y observe.
Luego, descomente el paso 2 y observe.
Haga esto hasta que haya descomentado los 6 pasos y haya observado sus comportamientos.
¿Qué puede concluir de todo esto? ¿Qué factores pueden cambiar el
contenSize
?\n
entonces el ancho de intrinsicContentSize será el ancho máximo de todas las líneas. Si una línea tiene 25 caracteres, otra tiene 2 caracteres y otra tiene 21 caracteres, su ancho se calculará en función de los 25 caracteresnumberOfLines
para0
que no tenga varias líneas. SunumberOfLines
ajustará de su intrinsicContentSize alturaCómo hacer ajustes: imagine que en función de su texto, el ancho
200
y el alto de su contenido intrínseco eran altos100
, pero desea limitar el ancho al contenedor de la etiqueta, ¿qué va a hacer? La solución es establecerlo en el ancho deseado. Para ello, establezcapreferredMaxLayoutWidth
que130
su nuevo intrinsicContentSize tendrá un ancho aproximado130
. La altura obviamente sería más que100
porque necesitarías más líneas. Dicho esto, si sus restricciones están configuradas correctamente, ¡no necesitará usar esto en absoluto! Para más información al respecto, vea esta respuesta y sus comentarios. Solo necesita usarlopreferredMaxLayoutWidth
si no tiene restricciones que restrinjan el ancho / alto, como en uno podría decir "no ajuste el texto a menos que exceda elpreferredMaxLayoutWidth
". Sin embargo, con 100% de certeza si se establece el líder / detrás ynumberOfLines
a0
continuación, usted es bueno! Larga historia corta, que la mayoría de las respuestas aquí recomendamos que se use se equivocan! Usted no lo necesita. Necesitarlo es una señal de que sus limitaciones no están configurados correctamente o simplemente no tienes restriccionesTamaño de fuente: también tenga en cuenta que si aumenta su tamaño de fuente, la altura del tamaño de contenido intrínseco aumentará. No lo mostré en mi código. Puedes probar eso por tu cuenta.
Entonces, de vuelta a su ejemplo de tableViewCell:
Todo lo que necesitas hacer es:
numberOfLines
a0
preferredMaxLayoutWidth
.fuente
En mi caso, tengo que crear una celda personalizada con una imagen que proviene del servidor y puede ser de cualquier ancho y alto. Y dos UILabels con tamaño dinámico (ancho y alto)
He logrado lo mismo aquí en mi respuesta con autolayout y programáticamente:
Básicamente por encima de la respuesta @smileyBorg ayudó, pero systemLayoutSizeFittingSize nunca funcionó para mí, en mi enfoque:
1. No se utiliza la propiedad de cálculo automático de altura de fila. 2. Sin uso de altura estimada 3. Sin necesidad de actualizaciones innecesarias Restricciones. 4.No se utiliza el ancho de diseño máximo preferido automático. 5. No uso systemLayoutSizeFittingSize (debería tener uso pero no funciona para mí, no sé lo que está haciendo internamente), sino que mi método - (flotante) getViewHeight funciona y sé lo que está haciendo internamente.
¿Es posible tener diferentes alturas en una celda UITableView cuando uso varias formas diferentes de mostrar la celda?
fuente
En mi caso, el relleno fue debido a las alturas sectionHeader y sectionFooter, donde el guión gráfico me permitió cambiarlo al mínimo 1. Entonces, en el método viewDidLoad:
fuente
Acabo de hacer algunos tratan de tonto y error con los valores de 2
rowHeight
yestimatedRowHeight
ya sólo pensé que podría proporcionar alguna información de depuración:Si los configura a ambos O solo configura el
estimatedRowHeight
, obtendrá el comportamiento deseado:Se sugiere que haga todo lo posible para obtener la estimación correcta, pero el resultado final no es diferente. Solo afectará su rendimiento.
Si solo establece la altura de fila, es decir, solo haga:
su resultado final no sería el deseado:
Si establece el valor
estimatedRowHeight
en 1 o menor, se bloqueará independientemente derowHeight
.Choqué con el siguiente mensaje de error:
fuente
Con respecto a la respuesta aceptada por @smileyborg, he encontrado
ser poco confiable en algunos casos donde las restricciones son ambiguas. Es mejor forzar el motor de diseño para calcular la altura en una dirección, utilizando la categoría de ayuda en UIView a continuación:
Donde w: es el ancho de la vista de tabla
fuente
Simplemente agregue estas dos funciones en su controlador de vista para resolver su problema. Aquí, list es una matriz de cadenas que contiene la cadena de cada fila.
fuente
fuente
Si la altura de la celda es dinámica por el contenido, debe contarla con precisión y luego devolver el valor de altura antes de que se renderice la celda. Una manera fácil es definir el método de conteo en el código de celda de la vista de tabla para que el controlador llame al método de delegado de altura de celda de tabla. No olvide contar el ancho real del marco de la celda (el valor predeterminado es 320) si la altura depende del ancho de la tabla o pantalla. Es decir, en el método de delegado de altura de celda de la tabla, use cell.frame para corregir el ancho de celda primero, luego llame al método de altura de conteo definido en la celda para obtener el valor adecuado y devolverlo .
PD. El código para generar el objeto de celda podría definirse en otro método para que llame al método de delegado de celda de vista de tabla diferente.
fuente
UITableView.automaticDimension
se puede configurar a través de Interface Builder:Xcode> Storyboard> Size Inspector
Celda de vista de tabla> Altura de fila> Automático
fuente
otra solución iOs7 + iOs8 en Swift
fuente
cellForRowAtIndexPath
, la celda aún no se presenta en este punto.