La altura de la vista de encabezado de la tabla es incorrecta cuando se usa el diseño automático, IB y tamaños de fuente

Estoy intentando crear una vista de encabezado para mi uiTableView (no un encabezado de sección, ya los tengo). He configurado un XIB en el constructor de interfaz. Todas las conexiones están conectadas y funciona maravillosamente … ¡excepto que la mesa no le da suficiente espacio! Mi problema es que la parte superior de la tabla superpone un poco el encabezado de la tabla.

My XIB está configurado con autlayout para todos los botones, y IB está feliz de que las restricciones no sean conflictivas / ambiguas. La vista se establece en el tamaño de forma libre, que en mi caso terminó siendo 320 x 471. Luego, en las restricciones para la vista, establezco un tamaño intrínseco para la vista de la misma.

Ahora esto funciona perfectamente con mi mesa. Todo se ve genial. Pero si cambio manualmente cualquiera de las fonts en la vista de encabezado con código, el diseño hace que la vista sea más grande y termina debajo de mi mesa.

¿Alguna idea de cómo hacer que TableViewcontroller deje suficiente espacio para la vista del encabezado después de configurar las fonts y los tamaños? Espero haber tenido sentido al explicar esto.

Nota: Puede encontrar una versión de Swift 3+ aquí: https://gist.github.com/marcoarment/1105553afba6b4900c10#gistcomment-1933639


La idea es calcular la altura del encabezado con la ayuda de systemLayoutSizeFittingSize:targetSize .

Devuelve el tamaño de la vista que satisface las restricciones que contiene. Determina el mejor tamaño de la vista considerando todas las restricciones que contiene y las de sus subvistas.

Después de cambiar la altura del encabezado, es necesario reasignar la propiedad tableHeaderView para ajustar las celdas de la tabla.

Basado en esta respuesta: Uso del diseño automático en UITableView para diseños dynamics de celdas y alturas de fila variables

 - (void)sizeHeaderToFit { UIView *header = self.tableView.tableHeaderView; [header setNeedsLayout]; [header layoutIfNeeded]; CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; CGRect frame = header.frame; frame.size.height = height; header.frame = frame; self.tableView.tableHeaderView = header; } 

Me encontré con un problema similar cuando estaba tratando de configurar mi encabezado de vista de tabla en una vista personalizada que definí con diseño automático usando el constructor de interfaz.

Cuando lo hiciera, encontraría que estaría oscurecido por un encabezado de sección.

Mi trabajo consistió en utilizar una “vista ficticia” como vista de encabezado de tabla y luego agregar mi vista personalizada a esa vista ficticia como una subvista. Creo que esto permite que el diseño automático configure la apariencia según las restricciones y el marco de la vista que lo contiene. Esto probablemente no es tan elegante como la solución de vokilam, pero funciona para mí.


 CGRect headerFrame = CGRectMake(0, 0, yourWidth, yourHeight); UIView *tempView = [[UIView alloc] initWithFrame:headerFrame]; [tempView setBackgroundColor:[UIColor clearColor]]; YourCustomView *customView = [[YourCustomView alloc] initWithFrame: headerFrame]; [tempView addSubview:movieHeader]; self.tableView.tableHeaderView = tempView; 

Debido a que su tableHeaderView está inited forma xib con diseño automático, por lo que las restricciones de su headerView personalizado y el superView se desconoce. Debe agregar las constraints de su headerView personalizado:

1.en viewDidLLoad asigna tu headerView personalizado a la tabla TableView’s HeaderView

  - (void)viewDidLoad { [super viewDidLoad]; UIView *yourHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"yourHeaderView" owner:nil options:nil] objectAtIndex:0]; //important:turn off the translatesAutoresizingMaskIntoConstraints;apple documents for details yourHeaderView.translatesAutoresizingMaskIntoConstraints = NO; self.tableView.tableHeaderView = yourHeaderView; } 

2.in – (void) updateViewConstraints, agregue las restricciones esenciales de su headerView personalizado

 - (void)updateViewConstraints { NSDictionary *viewsDictionary = @{@"headerView":yourHeaderView}; NSArray *constraint_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]" options:0 metrics:nil views:viewsDictionary]; NSArray *constraint_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(320)]" options:0 metrics:nil views:viewsDictionary]; [self.headerView addConstraints:constraint_H]; [self.headerView addConstraints:constraint_V]; NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]; NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]; [self.tableView addConstraints:constraint_POS_V]; [self.tableView addConstraints:constraint_POS_H]; [super updateViewConstraints]; } 

¡DE ACUERDO! PD: Aquí está el documento relacionado: Cambiar el tamaño de las vistas del controlador de vista

Lo que resolvió mi problema fue esto:

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() sizeHeaderToFit() } private func sizeHeaderToFit() { if let headerView = tableView.tableHeaderView { headerView.setNeedsLayout() headerView.layoutIfNeeded() let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height var newFrame = headerView.frame // Needed or we will stay in viewDidLayoutSubviews() forever if height != newFrame.size.height { newFrame.size.height = height headerView.frame = newFrame tableView.tableHeaderView = headerView } } } 

Encontré esta solución en alguna parte y funcionó como un hechizo, aunque no recuerdo dónde.

Encontré la respuesta de vokilam para que funcione bien. Aquí está su solución en Swift.

 func sizeHeaderToFit() { guard let header = tableView.tableHeaderView else { return } header.setNeedsLayout() header.layoutIfNeeded() let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height header.frame.size.height = height tableView.tableHeaderView = header } 

En mi caso, systemLayoutSizeFittingSize devuelve un tamaño incorrecto, porque una de las subvistas utiliza una restricción de relación de aspecto (ancho a alto) 4: 1.

Después de cambiarlo a un valor de restricción de altura constante (100), comienza a funcionar como se esperaba.

Combinando respuestas de @SwiftArchitect, @vokilam y @mayqiyue, y usando tableHeaderView creado por progtwig en lugar de un plumín (aunque, no veo ninguna razón por la que no debería funcionar con un plumín), y bajo iOS 10.x / Xcode 8.2.1, esto es lo que tengo funcionando:

Cree la vista en los métodos view- -viewDidLoad o init su controlador de vista, o donde sea que esté usando la vista de tabla:

 MyCustomTableHeaderView *myCustomTableHeaderView = [[MyCustomTableHeaderView alloc] init]; // Don't set its frame myCustomTableHeaderView.translatesAutoresizingMaskIntoConstraints = NO; self.myTableView.tableHeaderView = myCustomTableHeaderView; self.myCustomTableHeaderView = myCustomTableHeaderView; // We set and update our constraints in separate methods so we store the table header view in a UIView property to access it later 

Donde sea que configure las restricciones de su vista de encabezado personalizado (podría estar en `updateConstraints pero este método podría llamarse varias veces):

 // We use Pure Layout in our project, but the workflow is the same: // Set width and height constraints on your custom view then pin it to the top and left of the table view // Could also use VFL or NSLayoutConstraint methods [self.myCustomTableHeaderView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(self.superview.frame)]; // Width set to tableview's width [self.myCustomTableHeaderView autoSetDimension:ALDimensionHeight toSize:height]; // Whatever you want your height to be [self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeTop]; [self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeLeft]; // This is important [self.myCustomTableHeaderView layoutIfNeeded]; // We didn't need to call -setNeedsLayout or reassign our custom header view to the table view's tableHeaderView property again, as was noted in other answers 

Las otras respuestas me señalaron en la dirección correcta para obtener el TableHeaderView para cambiar el tamaño de forma adecuada. Sin embargo, estaba obteniendo un espacio entre el encabezado y las celdas tableView. Esto también podría hacer que sus celdas se superpongan con su encabezado, dependiendo de si el encabezado creció o se hizo más pequeño.

Pasé de esto:

  tableView.reloadData() let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height tableView.tableHeaderView?.frame.size.height = height 

Para arreglar la brecha / superposición todo lo que tenía que hacer era mover tableView.reloadData () a después de establecer la nueva altura en lugar de antes.

A esto:

  let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height tableView.tableHeaderView?.frame.size.height = height tableView.reloadData() 

sizeHeaderToFit sugerido por @vokilam no funcionó para mí.

Lo que funcionó es una versión modificada de @mayqiyue, invocada durante viewDidLoad , altura cableada, igual ancho a la vista de tabla.

 // Anchor the headerview, and set width equal to superview NSDictionary *viewsDictionary = @{@"headerView":self.tableView.tableHeaderView, @"tableView":self.tableView}; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(==tableView)]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView.tableHeaderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]" options:0 metrics:nil views:viewsDictionary]]; 

El siguiente código me ha funcionado: – Agregue esto en su clase UIView –

 - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.frame = CGRectMake(0, 0, self.frame.size.width, [[self class] height]); } return self; 

}

@rmigneco respuesta funcionó para mí, así que aquí está la versión rápida de la misma:

 let headerFrame = CGRectMake(0, 0, 100, 1); let tempView = UIView(frame: headerFrame); tempView.backgroundColor = UIColor.clearColor() let yourCustomView = CustomView(frame: headerFrame) tempView.addSubview(yourCustomView) self.tableView.tableHeaderView = tempView