2010-02-28 28 views
5

Tengo problemas para animar un encabezado de sección de UITableView personalizado.
El objetivo era crear secciones colapsables.
Cuando toco el encabezado personalizado la primera vez que se anima como se esperaba, sin embargo, cada vez que lo hago deja un duplicado en la ubicación original y anima otro.Sección UITableView Encabezado de sección personalizada, problema duplicado

imagen de ejemplo:

alt text http://img35.imageshack.us/img35/4018/screenshot2010022722565.png alt text http://img291.imageshack.us/img291/8287/screenshot2010022723035.png
Mi encabezado personalizado:

- (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 Animación Método:

- (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 lo que pasa, pero el las instancias sugieren que necesito tratar 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á causando la vista personalizada a la instancia. No puedo lanzar la vista porque la necesito como referencia para hacer la actualización de la animación. ¿Alguna idea sobre lo que puedo hacer para arreglar esto?

Respuesta

8

Solución encontrada.

La tabla debe volver a cargarse antes de cada cambio. De esta forma, la tabla está en el último estado antes de realizar cambios.

agregar [self.tableView reloadData]; como la primera entrada en el método "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]; 
} 
+0

Gracias, esto soluciona un problema relacionado en el que quería producir un efecto animado de eliminar/insertar las mismas filas, donde, sin llamar primero a 'reloadData', solo animaría las eliminaciones, pero no animaría las inserciones. Es un problema muy extraño. – Jeremy

+0

Buena manera ... + 1 para usted hombre – Sabby

2

I tenía un problema similar que fue causado por el uso de células altura dinámica. Tenía una vista de encabezado personalizado ampliable y cuando estaba actualizando tableView para insertar y eliminar las filas asociadas de la sección (lo que significa que se estaban expandiendo, respectivamente contrayendo), el encabezado de sección que era una subclase de UITableViewHeaderFooterView no se recicló. Así que, básicamente, se asignó y agregó una nueva sobre la anterior, lo que dio como resultado la superposición de vistas. El identificador de celda se configuró correctamente, por lo que debe haber sido otra cosa. Cuando eliminé tableView.sectionHeaderHeight = UITableViewAutomaticDimension e implementé func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat, la vista se recicló correctamente y solo se mostró una vista de encabezado 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 una UIView funciona bien. La idea es utilizar el mecanismo de reciclaje de UITableView a través de UITableViewCell y simplemente devolver su contenido después de configurarlo.

Conclusión. El problema es muy posible que sea causado por UITableViewHeaderFooterView cuando se usa con las celdas selfView de tableView y UITableViewAutomaticDimension en lugar de calcular manualmente la altura de la celda.

+0

Lo curioso que ya estaba usando UITableViewCells para los encabezados, no utilizando células auto-dimensionamiento, y todavía tenía el problema aquí :) – Gobe

Cuestiones relacionadas