Cómo expandir y contraer filas usando la sección del encabezado en un UITableView

Tengo una vista de tabla. Ahora quiero queuepsar y expandir filas tocando el encabezado de la sección. En otras palabras, cuando toco el encabezado, las filas se muestran para esa sección. ¿Cómo puedo hacer esto?

Elaboro un código para darte la idea. El concepto es que hacemos un seguimiento de la sección queuepsada en NSMutableSet y la agregamos / NSMutableSet acuerdo con el toque del usuario en la sección. La animation queuepso / expansión es en realidad la animation de agregar / eliminar celdas.

 #import "ViewController.h" @interface ViewController () < UITableViewDataSource, UITableViewDelegate> { NSMutableSet* _collapsedSections; } @property (nonatomic, weak) IBOutlet UITableView* tableView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _collapsedSections = [NSMutableSet new]; } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [_collapsedSections containsObject:@(section)] ? 0 : 10; } -(NSArray*) indexPathsForSection:(int)section withNumberOfRows:(int)numberOfRows { NSMutableArray* indexPaths = [NSMutableArray new]; for (int i = 0; i < numberOfRows; i++) { NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:section]; [indexPaths addObject:indexPath]; } return indexPaths; } -(void)sectionButtonTouchUpInside:(UIButton*)sender { sender.backgroundColor = [UIColor greenColor]; [self.tableView beginUpdates]; int section = sender.tag; bool shouldCollapse = ![_collapsedSections containsObject:@(section)]; if (shouldCollapse) { int numOfRows = [self.tableView numberOfRowsInSection:section]; NSArray* indexPaths = [self indexPathsForSection:section withNumberOfRows:numOfRows]; [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop]; [_collapsedSections addObject:@(section)]; } else { int numOfRows = 10; NSArray* indexPaths = [self indexPathsForSection:section withNumberOfRows:numOfRows]; [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop]; [_collapsedSections removeObject:@(section)]; } [self.tableView endUpdates]; //[_tableView reloadData]; } -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIButton* result = [UIButton buttonWithType:UIButtonTypeCustom]; [result addTarget:self action:@selector(sectionButtonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; result.backgroundColor = [UIColor blueColor]; [result setTitle:[NSString stringWithFormat:@"Section %d", section] forState:UIControlStateNormal]; result.tag = section; return result; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; result.textLabel.text = [NSString stringWithFormat:@"Cell %d", indexPath.row]; return result; } @end 

Como ya esta es una vieja pregunta ahora. También me searchon y en el último obtuvo un código de ejemplo de Github. Por lo tanto, pensé en compartir el enlace, si en un futuro cercano a alguien se le ocurren los mismos problemas. https://github.com/iSofTom/STCollapseTableView

TLIndexPathTools hace esto con solo unas pocas líneas de código de su parte. Intente ejecutar el proyecto de ejemplo Collapse . Es subclasss TLCollapsibleTableViewController , que tiene un par de buenas opciones. Es compatible con la expansión de una sola sección a la vez o múltiples secciones. También optimiza la position de desplazamiento al expandir una sección para mostrar tantas filas de la sección como sea posible. Por lo tanto, si toca una sección cerca de la parte inferior de la pantalla, se desplazará hacia arriba automáticamente.

El código de controller de vista completa del proyecto de muestra es el siguiente:

 #import "TLCollapsibleTableViewController.h" @interface CollapseTableViewController : TLCollapsibleTableViewController - (IBAction)toggleSingleSectionExpanded:(UISwitch *)sender; @end #import "CollapseTableViewController.h" #import "TLIndexPathSectionInfo.h" #import "TLCollapsibleDataModel.h" #define SECTION1_NAME @"Section 1" #define SECTION2_NAME @"Section 2" @interface CollapseTableViewController () @property (strong, nonatomic) TLIndexPathDataModel *backingDataModel; @end @implementation CollapseTableViewController - (void)viewDidLoad { [super viewDidLoad]; //define items for two sections NSArray *section1Items = @[ @"Fnetworkingricksburg", @"George Washington", @"Grand Canyon"]; NSArray *section2Items = @[ @"Jelly Bean", @"Bibliography", @"Keyboard Shortcut", @"Metadata", @"Fundamental", @"Cellar Door"]; //We're using plain string items, so we don't have a sectionNameKeyPath property //to use, so instead we explicitly create section info objects TLIndexPathSectionInfo *section1 = [[TLIndexPathSectionInfo alloc] initWithItems:section1Items andName:SECTION1_NAME]; TLIndexPathSectionInfo *section2 = [[TLIndexPathSectionInfo alloc] initWithItems:section2Items andName:SECTION2_NAME]; //create the backing model, which contains all sections and items self.backingDataModel = [[TLIndexPathDataModel alloc] initWithSectionInfos:@[section1, section2] andIdentifierKeyPath:nil andCellIdentifierKeyPath:nil]; [self collapseAll]; } - (void)tableView:(UITableView *)tableView configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { NSString *item = [self.dataModel itemAtIndexPath:indexPath]; cell.textLabel.text = item; } - (IBAction)toggleSingleSectionExpanded:(UISwitch *)sender { self.singleExpandedSection = sender.isOn; [self collapseAll]; } - (void)collapseAll { self.dataModel = [[TLCollapsibleDataModel alloc] initWithBackingDataModel:self.backingDataModel collapsedSectionNames:[NSSet setWithArray:self.backingDataModel.sectionNames]]; } @end 

configure viewForHeaderInSection:

Me gusta esto

 (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ UILabel *lblHeader = [[UILabel alloc]init]; lblHeader.text = @"Section 0"; lblHeader.backgroundColor = [UIColor blueColor]; lblHeader.font = [UIFont fontWithName:@"Avenir" size:18]; lblHeader.textAlignment=NSTextAlignmentLeft; lblHeader.userInteractionEnabled=YES; UIGestureRecognizer *gr; if(section==0){ lblHeader.text = @"Section 0"; gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; }else if(section == 1){ lblHeader.text = @"Section 1"; gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture1:)]; } [lblHeader addGestureRecognizer:gr]; return lblHeader; } 

luego escribe llamadas de acción separadas

 - (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer { } - (void)handleGesture1:(UIGestureRecognizer *)gestureRecognizer { }