我有一个表格视图。现在我想通过点击节标题来折叠和展开行。换句话说,当我点击标题时,行显示该部分。我怎么能这样做?
答案 0 :(得分: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
答案 1 :(得分:3)
因为现在这已经是一个老问题了。我也搜索了,并且在最后得到了来自Github的1个示例代码。所以我想共享链接,如果在不久的将来任何人提出相同的问题。 https://github.com/iSofTom/STCollapseTableView
答案 2 :(得分: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
答案 3 :(得分: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 {
}