6

我有一个表格视图。现在我想通过点击部分标题来折叠和展开行。换句话说,当我点击标题时,会显示该部分的行。我怎样才能做到这一点?

4

4 回答 4

33

我起草了一些代码来给你这个想法。这个概念是我们跟踪折叠的部分,NSMutableSet并根据用户对部分的触摸来添加/删除它。折叠/展开动画实际上是添加/删除单元格的动画。

#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
于 2013-06-22T08:13:35.167 回答
3

因为这已经是一个老问题了。我也搜索过,最后从 Github 获得了 1 个示例代码。所以我想分享链接,如果在不久的将来有人遇到同样的问题。 https://github.com/iSofTom/STCollapseTableView

于 2014-07-10T12:02:40.653 回答
1

TLIndexPathTools只需几行代码就可以做到这一点。尝试运行Collapse示例项目。它的子类TLCollapsibleTableViewController,它有几个不错的选择。它支持一次扩展单个部分或多个部分。当您展开一个部分以显示该部分的尽可能多的行时,它还会优化滚动位置。因此,如果您点击屏幕底部附近的部分,它将自动向上滚动。

示例项目的全视图控制器代码如下:

#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 = @[
                               @"Fredricksburg",
                               @"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
于 2013-06-22T11:03:31.970 回答
0

配置 viewForHeaderInSection:

像这样

(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;
}

然后编写单独的动作调用

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

- (void)handleGesture1:(UIGestureRecognizer *)gestureRecognizer { 
}
于 2013-09-25T10:51:59.123 回答