Encabezado de sección personalizada UITableView, problema duplicado
-
23-09-2019 - |
Pregunta
Tengo problemas para animar un encabezado de sección UITableView personalizado.
El objetivo era crear secciones plegables.
Cuando toco el encabezado personalizado la primera vez, se anima como se esperaba, sin embargo, cada vez posterior deja un duplicado en la ubicación original y anima otro.
Ejemplo de imagen:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView* customView = [[[UIView alloc]initWithFrame:CGRectMake(10.0, 0.0, 300.0, 44.0)]autorelease];
customView.backgroundColor = [UIColor lightGrayColor];
UILabel * headerLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.opaque = NO;
headerLabel.textColor = [UIColor darkGrayColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.frame = CGRectMake(10, 7, 260.0, 44.0);
headerLabel.textAlignment = UITextAlignmentCenter;
NSDictionary *dictionary = [self.data objectAtIndex:section];
headerLabel.text = [dictionary objectForKey:@"Title"];
[customView addSubview:headerLabel];
// add button to right corner of section
UIButton* headerButton = [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 320, 44)];
headerButton.center = CGPointMake( 160.0, 22.0);
headerButton.backgroundColor = [UIColor clearColor];
headerButton.tag = section;
[headerButton addTarget:self action:@selector(expandSection:) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:headerButton];
return customView;
}
Mi método de animación:
- (void) expandSection:(id)sender {
if (expandedSection == [sender tag]) {
expandedSection = -1;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
}else if (expandedSection == -1){
expandedSection = [sender tag];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
}else{
[self.tableView beginUpdates];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:expandedSection] withRowAnimation:UITableViewRowAnimationNone];
expandedSection = [sender tag];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
//[self.tableView reloadData];
}
No estoy exactamente seguro de qué está pasando, pero los casos sugieren que necesito solucionar algo.He intentado algunas cosas pero no puedo resolver esto.¡Cualquier persona que ayude con esto sería genial!
Editar:Creo que el problema es que reloadSections está provocando que se cree una instancia de la vista personalizada.No puedo liberar la vista porque la necesito como referencia para realizar la actualización de la animación.¿Alguna idea sobre lo que puedo hacer para solucionar este problema?
Solución
solución encontrada.
La tabla necesita ser recargado antes de cada cambio. De esta manera la tabla se encuentra en el último estado antes de hacer cualquier cambio.
add [Self.tableView reloadData]; como la entrada puño en el método de "expandSection".
CÓDIGO:
- (void) expandSection:(id)sender {
[self.tableView reloadData];
if (expandedSection == [sender tag]) {
expandedSection = -1;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
}else if (expandedSection == -1){
expandedSection = [sender tag];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
}else{
[self.tableView beginUpdates];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:expandedSection] withRowAnimation:UITableViewRowAnimationNone];
expandedSection = [sender tag];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[sender tag]] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
//[self.tableView reloadData];
}
Otros consejos
I tenía un problema similar que fue causado por el uso de células de altura dinámica. Tenía una vista encabezado personalizado expandible y cuando estaba actualizando tableView insertar y quitar las filas asociadas de la sección (lo que significa que se estaban expandiendo, respectivamente colapso), el encabezado de sección, que fue una subclase de UITableViewHeaderFooterView
no se recicló. Así que, básicamente uno nuevo se asigna y se añadió durante la anterior resulta en la superposición de puntos de vista. La célula se estableció identificador propiamente debe haber sido algo más. Cuando quité tableView.sectionHeaderHeight = UITableViewAutomaticDimension
e implementé func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
la vista quedó adecuadamente reciclado y sólo una vista de encabezado se muestra para cada sección.
Otra solución que resultó en realidad el trabajo era utilizar UITableViewCell
en lugar de UITableViewHeaderFooterView
y cuando regrese en func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
que acaba de return cell.contenView
, esto funciona porque el método requiere para devolver un UIView y desde el contentView
del UITableViewCell es un UIView funciona muy bien. La idea detrás es utilizar el mecanismo de reciclaje de UITableView través UITableViewCell y simplemente devolver su contenido después de configurar la misma.
Conclusión. El problema es muy posible que es causada por UITableViewHeaderFooterView
cuando se utiliza con auto calibrado células tableView y UITableViewAutomaticDimension
en lugar de calcular manualmente altura de la celda.