展开和折叠 tableView 部分 iOS?

Expanding and collapsing tableView sections iOS?

我能够成功展开和折叠 tableView 部分,但是我无法对单个部分执行此操作,因此 far.So 所有部分同时折叠或展开,这是因为我调用 [tableView reloadData] .那么如何展开或折叠特定部分?

这是我目前的做法。

  -(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
  {
     headerLabel = [[UILabel alloc]init];
     headerLabel.tag = section;
     headerLabel.userInteractionEnabled = YES;
     headerLabel.backgroundColor = [[UIColor grayColor]colorWithAlphaComponent:0.2];
     headerLabel.text = [menuCategoryArray objectAtIndex:section];
     headerLabel.frame = CGRectMake(5, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height);


     UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(headerClicked:)];
     tapGesture.cancelsTouchesInView = NO;
     [headerLabel addGestureRecognizer:tapGesture];

     return headerLabel;


 }

 -(void)headerClicked:(UIGestureRecognizer*)sender
 {

    if (!isShowingList) {
    isShowingList=YES;
    [self.menuTableView reloadData];
    UILabel *lbl = (UILabel*)sender.view;
    NSLog(@"header no : %d", lbl.tag);

   }else{

    isShowingList=NO;
    [self.menuTableView reloadData];
    UILabel *lbl = (UILabel*)sender.view;
    NSLog(@"header no : %d", lbl.tag);

  }


  }

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

if (isShowingList) {

    return [[[[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"] objectAtIndex:section] count];

}else{
    return 0;
}
return 0;

}

你真的最好不要使用 'tableView update block'。请查看此 viewController 以获得我最近发布的答案。 updateBlock 允许您操作一些变量或其他影响数据源的变量,并指示 table 到 add/remove rows/sections 以反映该更改。请注意,当您调用 endUpdates 方法时,table 不得与模型冲突,否则您将得到一个异常。

#import "ViewController.h"

//dont worry, the header is empty except for import <UIKit/UIKit.h>, this is a subclass on UIViewController

@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>

@property (weak, nonatomic) UITableView *tableView;


@end

@implementation ViewController
{
//ivars
  BOOL sectionIsOpen[4]; //we will use this BOOL array to keep track of the open/closed state for each section.  Obviously I have the number of sections fixed at 4 here, but you could make a more dynamic array with malloc() if neccesary..
}



- (void)viewDidLoad {
  [super viewDidLoad];

  UITableView *tv = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
  tv.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  tv.dataSource = self;
  tv.delegate = self;

  [self.view addSubview:tv];
  self.tableView = tv;

  // Do any additional setup after loading the view, typically from a nib.
}

#pragma mark - UITableViewDataSource
-(NSInteger )numberOfSectionsInTableView:(UITableView *)tableView{
  return 4;
}

-(NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  return ((sectionIsOpen[section]) ? [self numberOfRowsInSection:section] : 0);
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

  //put your switch() here...

  return [NSString stringWithFormat:@"I am section %i", (int)section ];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

  static NSString *cellId = @"cellID";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];

  if (!cell) {
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
  }


 //etc etc decorate your cell...
  cell.textLabel.text = [NSString stringWithFormat:@"cell %i / %i", (int)indexPath.section, (int)indexPath.row ];


  return cell;
}
#pragma mark - UITableViewDelegate
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

  const CGRect fr = CGRectMake(0, 0, 320.0, 40.0 );

  UIButton *btn = [[UIButton alloc]initWithFrame:fr];
  [btn setTitle:[self tableView:tableView titleForHeaderInSection:section] forState:UIControlStateNormal ];
  [btn setTag:section];
  [btn addTarget:self action:@selector(sectionOpenToggle:) forControlEvents:UIControlEventTouchUpInside];


  // add an image, colour etc if you like

  return btn;
}



#pragma mark - tableViewHelpers

//the number of rows in sectionX when it is open...
-(NSInteger )numberOfRowsInSection:(NSInteger )section{
//get your count from your model
  return section + 1;
}

//opening/closing a section
-(void )setSection:(NSInteger )section toOpen:(BOOL )open{

  if (open != sectionIsOpen[section]) {

//build an array of indexPath objects
    NSMutableArray *indxPths = [NSMutableArray array];
    for (NSInteger row = 0; row < [self numberOfRowsInSection:section]; row ++) {

      [indxPths addObject: [NSIndexPath indexPathForRow:row inSection:section ]
       ];

    }


    [self.tableView beginUpdates];

    if (open) {
      [self.tableView insertRowsAtIndexPaths:indxPths withRowAnimation:UITableViewRowAnimationFade];
      //nb there is a large ENUM of tableViewRowAnimation types to experiment with..

    }else{
      [self.tableView deleteRowsAtIndexPaths:indxPths withRowAnimation:UITableViewRowAnimationFade];

    }
    sectionIsOpen[section] = open;
    [self.tableView endUpdates];

  }
}

-(void )sectionOpenToggle:(id )sender{
  [self setSection:[sender tag] toOpen: !sectionIsOpen[[sender tag]] ];
}

// open/close all sections.
-(void )setAllSectionsOpen:(BOOL )open{

  for (NSInteger section = 0; section < [self numberOfSectionsInTableView:self.tableView]; section ++) {
    [self setSection:section toOpen:open];
  }
}


//these two for your convenience, hook up to navbar items etc..
-(IBAction)openAllSections:(id)sender{
  [self setAllSectionsOpen:YES];
}
-(IBAction)closeAllSections:(id)sender{
  [self setAllSectionsOpen:NO];
}
@end

先取isShowingList

@property (nonatomic, strong) NSMutableArray *isShowingList;

为了识别之前打开的部分,您需要另一个 属性

@property (nonatomic, assign) NSInteger openSectionIndex;

当您初始化数据时,在您的情况下为 isShowingList,在重新加载之前初始化 isShowingList 数组 table

self.isShowingList = [NSMutableArray array];
if (jsonArray && [jsonArray valueForKey:@"menus"] && [[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"]) {
    for (int i = 0; i < [[[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"] count]; i++) {
        [self.isShowingList addObject:[NSNumber numberWithBool:NO]];
    }
} 

并像这样在 viewDidLoad() 中初始化 openSectionIndex

self.openSectionIndex = NSNotFound;

并且您的代码应该像这样更改

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if ([[self.isShowingList objectAtIndex:section] boolValue]) {
        return [[[[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"] objectAtIndex:section] count];
    } else {
        return 0;
    }
    return 0;
}

-(void)headerClicked:(UIGestureRecognizer*)sender {
    UILabel *lbl = (UILabel*)sender.view;
    NSLog(@"header no : %d", lbl.tag);
    if ([[self.isShowingList objectAtIndex:lbl.tag] boolValue]) {
        [self closeSection:lbl.tag];
    } else {
        [self openSection:lbl.tag];
    }
}

//methods for expanding and collapsing sections
- (void)openSection:(NSInteger)section {
    [self.isShowingList replaceObjectAtIndex:section withObject:[NSNumber numberWithBool:YES]];
    NSInteger countOfRowsToInsert = [[[[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"] objectAtIndex:section] count];
    NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
    for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
        [indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:section]];
    }
    NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
    NSInteger previousOpenSectionIndex = self.openSectionIndex;
    if (previousOpenSectionIndex != NSNotFound) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.menuTableView reloadSections:[NSIndexSet indexSetWithIndex:previousOpenSectionIndex] withRowAnimation:UITableViewRowAnimationNone];
        });
        [self.isShowingList replaceObjectAtIndex:previousOpenSectionIndex withObject:[NSNumber numberWithBool:NO]];
        NSInteger countOfRowsToDelete = [[[[jsonArray valueForKey:@"menus"] valueForKey:@"menuName"] objectAtIndex:previousOpenSectionIndex] count];
        for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
            [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenSectionIndex]];
        }
    }
    // Apply the updates.
    [self.menuTableView beginUpdates];
    [self.menuTableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.menuTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.menuTableView endUpdates];
    self.openSectionIndex = section;
}

- (void)closeSection:(NSInteger)section {
    [self.isShowingList replaceObjectAtIndex:section withObject:[NSNumber numberWithBool:NO]];
    NSInteger countOfRowsToDelete = [self.menuTableView numberOfRowsInSection:section];
    if (countOfRowsToDelete > 0) {
        NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
        for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
            [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:section]];
        }
        [self.menuTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop];
    }
    self.openSectionIndex = NSNotFound;
}