Desde que descubrí AutoLayout
que lo uso en todas partes, ahora intento usarlo con un tableHeaderView
.
Hice una subclass
de UIView
agregado todo (etiquetas etc ...) que quería con sus limitaciones, y luego añadí esta CustomView
a la UITableView
' tableHeaderView
.
Todo funciona bien, excepto las UITableView
siempre aparece por encima de la CustomView
, por encima me refiero al CustomView
decir bajo el UITableView
por lo que no puede ser visto!
Parece que no importa lo que haga, el height
del UITableView
' tableHeaderView
es siempre 0 (también lo es el ancho, xey).
Mi pregunta: ¿es posible lograr esto sin configurar el marco manualmente ?
EDITAR:
El CustomView
' subview
que estoy usando tiene estas restricciones:
_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];
Estoy usando una biblioteca práctica 'KeepLayout' porque escribir restricciones manualmente toma una eternidad y demasiadas líneas para una sola restricción, pero los métodos son autoexplicativos.
Y UITableView
tiene estas limitaciones:
_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];
_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;
No sé si tengo que establecer algunas restricciones directamente en el CustomView
, creo que la altura de CustomView está determinada por las restricciones en el UILabel
"título" en él.
EDITAR 2: Después de otra investigación, parece que la altura y el ancho de CustomView se calcularon correctamente, pero la parte superior de CustomView todavía está al mismo nivel que la parte superior de UITableView y se mueven juntos cuando me desplazo.
fuente
Respuestas:
Pregunté y respondí una pregunta similar aquí . En resumen, agrego el encabezado una vez y lo uso para encontrar la altura requerida. Luego, esa altura se puede aplicar al encabezado, y el encabezado se establece una segunda vez para reflejar el cambio.
Si tiene etiquetas de varias líneas, esto también se basa en la configuración de la vista personalizada PreferredMaxLayoutWidth de cada etiqueta:
o quizás más en general:
Actualización de enero de 2015
Desafortunadamente, esto todavía parece necesario. Aquí hay una versión rápida del proceso de diseño:
Me resultó útil mover esto a una extensión en UITableView:
Uso:
fuente
preferredMaxLayoutWidth
es agregar una restricción de ancho (igual al ancho de la vista de tabla) en la vista del encabezado antes de usarsystemLayoutSizeFittingSize:
.self.tableView.tableHeaderView
let height = header.systemLayoutSizeFittingSize(CGSizeMake(CGRectGetWidth(self.bounds), 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
header.setNeedsLayout() header.layoutIfNeeded() header.frame.size = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) self.tableHeaderView = header
funcionaría en iOS 10.2No pude agregar una vista de encabezado usando restricciones (en el código). Si le doy a mi vista una restricción de ancho y / o alto, aparece un bloqueo con el mensaje que dice:
Cuando agrego una vista en el guión gráfico a la vista de mi tabla, no muestra restricciones y funciona bien como vista de encabezado, por lo que creo que la ubicación de la vista de encabezado no se realiza mediante restricciones. No parece comportarse como una vista normal en ese sentido.
El ancho es automáticamente el ancho de la vista de tabla, lo único que necesita establecer es la altura; los valores de origen se ignoran, por lo que no importa lo que ingrese para esos. Por ejemplo, esto funcionó bien (al igual que 0,0,0,80 para el rect):
fuente
translatesAutoresizingMaskIntoConstraints = NO
. Activar la traducción evita el error: sospecho que aUITableView
partir de la versión 7.1 no se intenta crear un diseño automático de su vista de encabezado y quiere algo con el marco preestablecido.Vi muchos métodos aquí haciendo tantas cosas innecesarias, pero no necesitas tanto para usar el diseño automático en la vista del encabezado. Solo tiene que crear su archivo xib, poner sus restricciones e instanciarlo así:
fuente
Otra solución es enviar la creación de la vista del encabezado a la siguiente llamada del hilo principal:
Nota: Soluciona el error cuando la vista cargada tiene una altura fija. No lo he probado cuando la altura del encabezado solo depende de su contenido.
EDITAR:
Puede encontrar una solución más limpia a este problema implementando esta función y llamándola en
viewDidLayoutSubviews
fuente
tableHeaderView
son una especie de errores con el diseño automático. Hay algunas soluciones alternativas, como esta. Pero desde que escribí esto, he encontrado una solución mejor y más limpio aquí stackoverflow.com/a/21099430/127493 llamando a su- (void)sizeHeaderToFit
enviewDidLayoutSubviews
Código:
fuente
Amplió esta solución http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/ para la vista del pie de página de la tabla:
fuente
self.tableFooterView.transform
parte? ¿Por qué es necesario?Puede obtener el diseño automático para proporcionarle un tamaño mediante el método systemLayoutSizeFittingSize .
Luego puede usar esto para crear el marco para su aplicación. Esta técnica funciona siempre que necesite saber el tamaño de una vista que usa el diseño automático internamente.
El código en Swift parece
O en Objective-C
También debe tenerse en cuenta que en esta instancia en particular, anular requireConstraintBasedLayout en su subclase, da como resultado que se realice una pasada de diseño, sin embargo, los resultados de esta pasada de diseño se ignoran y el marco del sistema se establece en el ancho de tableView y 0 de altura.
fuente
Lo siguiente funcionó para mí.
UIView
vista de encabezado simple y antigua .UIView
El principal beneficio que veo es limitar los cálculos de marcos. Apple realmente debería actualizar
UITableView
la API para hacerlo más fácil.Ejemplo usando SnapKit:
fuente
Suceden cosas extrañas. systemLayoutSizeFittingSize funciona muy bien para iOS9, pero no para iOS 8 en mi caso. Entonces este problema se resuelve con bastante facilidad. Simplemente obtenga el enlace a la vista inferior en el encabezado y en viewDidLayoutSubviews después de la super llamada actualice los límites de la vista del encabezado insertando la altura como CGRectGetMaxY (yourview.frame) + padding
UPD: La solución más fácil de todos : Entonces, en la vista de encabezado, coloque la subvista y fíjela a la izquierda , derecha , arriba . En esa subvista, coloque sus subvistas con restricciones de altura automática. Después de eso, dé todo el trabajo al diseño automático (no se requiere cálculo)
Como resultado, la subvista se expande / contrae como debería, al final llama a viewDidLayoutSubviews. En ese momento, sabemos el tamaño real de la vista, así que configure headerView height y actualícelo reasignando. ¡Funciona de maravilla!
También funciona para la vista de pie de página.
fuente
Actualizado para Swift 4.2
fuente
puede agregar una restricción de ubicación superior + horizontal entre el encabezado y la vista de tabla, para colocarlo correctamente (si el encabezado en sí contiene todas las restricciones de diseño internas necesarias para tener un marco correcto)
en el método tableViewController viewDidLoad
fuente
Mi vista de encabezado de tabla es una subclase de UIView: creé una única UIView de contentView dentro del inicializador, con sus límites iguales a los del marco de la vista de encabezado de tabla y agregué todos mis objetos como una subvista de eso.
Luego agregue las restricciones para sus objetos dentro del
layoutSubviews
método de la vista del encabezado de la tabla en lugar de dentro del inicializador. Eso resolvió el accidente.fuente
Mi AutoLayout funciona muy bien:
fuente
Para la mayoría de los casos, la mejor solución es simplemente no luchar contra el marco y adoptar máscaras de autoresización:
Al usar máscaras de tamaño automático, le está diciendo al marco cómo su vista debería cambiar su tamaño cuando la supervista cambia su tamaño. Pero este cambio se basa en el marco inicial que ha establecido.
fuente
Sé que esta es una publicación antigua, pero después de revisar todas las publicaciones de SO sobre esto y pasar una tarde entera jugando con esto, finalmente encontré una solución limpia y muy simple.
En primer lugar, la jerarquía de mi vista se ve así:
tableHeaderView
Ahora, dentro de la Vista (n. ° 3), configuré todas las restricciones como lo haría normalmente, incluido el espacio inferior al contenedor. Esto hará que el contenedor (es decir, 3.View, es decir, headerView) se dimensione a sí mismo en función de sus subvistas y sus limitaciones.
Después de eso, establezco las restricciones entre
3. View
y2. View
a estos:Note que omito intencionalmente el espacio inferior intencionalmente.
Una vez que todo esto está hecho en el guión gráfico, todo lo que queda por hacer es pegar esas tres líneas de códigos:
fuente
Consejos: Si usa el método setAndLayoutTableHeaderView, debe actualizar el marco de las subvistas, por lo que en esta situación UILabel's favoriteMaxLayoutWidth debe llamar antes de que se llame a systemLayoutSizeFittingSize, no llame a layoutSubview.
demostración de código
fuente
Comparte mi enfoque.
UITableView+XXXAdditions.m
Uso.
fuente
En mi caso, el método con systemLayoutSizeFittingSize por alguna razón no funcionó. Lo que funcionó para mí es una modificación de la solución publicada por HotJard (su solución original tampoco funcionó en mi caso en iOS 8). Lo que tenía que hacer es colocar una subvista en la vista de encabezado y fijarla a la izquierda, derecha, arriba (no fijarla a la parte inferior). Ponga todo usando autolayout en esa subvista y en el código haga esto:
fuente
Una publicación antigua. Pero una buena publicación. Aquí están mis 2 centavos.
En primer lugar, asegúrese de que su vista de encabezado tenga sus restricciones dispuestas para que pueda admitir su propio tamaño de contenido intrínseco. Luego haz lo siguiente.
fuente
Pude lograrlo con el siguiente enfoque (esto funciona para el pie de página de la misma manera).
Primero, necesitará pequeños
UITableView
extensión:Swift 3
En su implementación de la clase de controlador de vista:
Notas sobre
UIView
la implementación de una subvista de un encabezado :Tienes que estar 100% seguro de que tu vista de encabezado tiene la configuración correcta de diseño automático. Recomendaría comenzar con una vista de encabezado simple con solo una restricción de altura y probar la configuración anterior.
Anular
requiresConstraintBasedLayout
y devolvertrue
:.
fuente
Para usuarios de Xamarin:
Suponiendo que nombró la vista de encabezado de su vista de tabla como TableviewHeader
fuente
Así es como puede hacerlo en su
UIViewController
fuente
Cualquier basada en restricciones
UIView
puede ser una buenatableHeaderView
.Es necesario establecer un
tableFooterView
antes y luego imponer una restricción final adicional entableFooterView
ytableHeaderView
.}
Puede encontrar todos los detalles y fragmentos de código aquí.
fuente
He descubierto una solución. envuelva su vista de encabezado xib de autolayout wrriten en un contenedor uiview vacío, y asigne la vista de encabezado a la propiedad tableViewHeader de tableView.
fuente
Esto es lo que funciona para UITableViewController en ios 12,
Coloque un UIView en TableView encima de todas las celdas prototipo para el encabezado y debajo de todas las celdas prototipo para el pie de página. Configure su encabezado y pie de página según sea necesario. Establezca todas las restricciones necesarias.
Ahora use los siguientes métodos de extensión
y llámelo en ViewDidLayoutSubviews de la subclase de UITableViewController
fuente
Encontré el problema de obtener un ancho de 375 puntos, la única forma en que funcionó para mí es retransmitir el tableView para obtener el ancho correcto. También preferí el Autodiseño a la configuración del tamaño del marco.
Aquí está la versión que me funciona:
Xamarin.iOS
Versión Swift (modificado de la respuesta de @Ben Packard)
fuente
Creé una subclase de
UITableView
y la utilicéUIStackView
tanto para el encabezado como para el pie de página, también permite configurar más de una vista.https://github.com/omaralbeik/StackableTableView
fuente
Mi solución es hacer una nueva clase como esta.
Para usarlo, simplemente agregue todas sus subvistas en una instancia de
BaseTableHeaderView
y adjúntelo a su vista de tabla.Cambiará el tamaño automáticamente en función de sus limitaciones.
fuente
La respuesta aceptada solo es útil para tablas con una sola sección. Para múltiples secciones,
UITableView
asegúrese de que su encabezado herede deUITableViewHeaderFooterView
y estará bien.Como alternativa, simplemente inserte su encabezado actual en el formato
contentView
deUITableViewHeaderFooterView
. Exactamente comoUITableViewCell
funciona.fuente
tableHeaderView
el encabezado de la sección.