UITableView是列表视图,类似于QQAPP中联系人页面的功能。
UITableView是UIScrollView的子类,默认拥有UIScrollView的滚动功能,而不用设置contentSize
使用注意事项
1必须添加协议,以及实现代理方法
1-1 UITableViewDelegate 视图代理
1-2 UITableViewDataSource 数据源代理
2 初始化时,必须使用方法 - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
3 列表类型UITableViewStyle设置时,注意差异,如:
3-1 UITableViewStyleGrouped,如果有多个section时,当前section页眉不会在最顶端显示
3-2 UITableViewStylePlain,如果有多个section时,当前section页眉会在最顶端显示
4代理方法实现中,注意相同功能代理方法实现的冲突,如:
4-1 - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section与 - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section不能同时设置
4-2 - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section与 - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section不能同时设置
5、注意复用技术
5-1 UITableViewCell的复用
5-2 每个section中页眉视图的复用
5-3 每个section中页脚视图的复用
- @interface ViewController () <UITableViewDataSource, UITableViewDelegate>
- @property (nonatomic, strong) UITableView *tableview;
- @property (nonatomic, strong) NSMutableArray *mainArray; // 数据源
- @property (nonatomic, strong) NSMutableArray *boolArray; // 用于控制section行数的数据源,即控制section的展开,或折叠
- @end
- // 设置数据源
- NSInteger sectionCount = arc4random() % 10 + 1; // 随机数
- sectionCount = 10;
- self.mainArray = [[NSMutableArray alloc] init];
- for (int i = 0; i < sectionCount; i++)
- {
- NSInteger rowCount = arc4random() % 10 + 1; // 随机数
- rowCount = 10;
- NSMutableArray *array = [NSMutableArray arrayWithCapacity:rowCount];
- for (int j = 0; j < rowCount; j++)
- {
- NSString *rowText = [NSString stringWithFormat:@"section(%@)-row(%@)", @(i + 1), @(j + 1)];
- [array addObject:rowText];
- }
- NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
- [dict setObject:[NSString stringWithFormat:@"section(%@)", @(i + 1)] forKey:@"title"];
- [dict setObject:array forKey:@"array"];
- [self.mainArray addObject:dict];
- }
- self.boolArray = [[NSMutableArray alloc] init];
- for (int i = 0; i < sectionCount; i++)
- {
- // 1为展开,0为折叠
- [self.boolArray addObject:@(1)];
- }
- self.tableview = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
- [self.view addSubview:self.tableview];
- self.tableview.backgroundColor = [UIColor redColor];
- /*
- 设置代理
- 1 设置实现代理方法的对象
- 2 添加协议
- 3 实现代理方法
- */
- self.tableview.delegate = self;
- self.tableview.dataSource = self;
- // 其他属性
- // 头部视图
- UIImageView *headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 200.0)];
- headerView.image = [UIImage imageNamed:@"headerImage"];
- self.tableview.tableHeaderView = headerView;
- // 尾部视图
- UIImageView *footerView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 200.0)];
- footerView.image = [UIImage imageNamed:@"footerImage"];
- self.tableview.tableFooterView = footerView;
- // 滚动回顶端,即点击状态栏视图时,自动滚动回顶端,默认YES,即打开
- self.tableview.scrollsToTop = YES;
- // UITableViewCell中分割线的颜色
- self.tableview.separatorColor = [UIColor purpleColor];
- // UITableViewCell中分割线样式,默认单条线,即UITableViewCellSeparatorStyleSingleLine
- self.tableview.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
- // UITableViewCell中分割线对齐,默认有间距(注意:与UITableViewCell的 separatorInset、layoutMargins 属性同时设置才有效)
- self.tableview.separatorInset = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
- self.tableview.layoutMargins = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
- // UITableViewDataSource
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- // 总共有多少个section,默认是1个
- NSInteger count = self.mainArray.count;
- return count;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- // 每个section有多少个row
- NSDictionary *dict = self.mainArray[section];
- NSArray *array = [dict objectForKey:@"array"];
- NSInteger count = 0;
- NSNumber *openNumber = self.boolArray[section];
- if (openNumber.intValue == 1)
- {
- count = array.count;
- }
- return count;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- // 每个row中具体视图UITableViewCell
- // 复用标识符
- static NSString *const identifier = @"UITableViewCell";
- // 未复用标识
- // NSString *identifier = [NSString stringWithFormat:@"%@", indexPath];
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
- if (cell == nil)
- {
- /*
- 注意:
- 实例化时样式为 UITableViewCellStyleSubtitle 时在主标题下面显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleSubtitle 时在主标题下面显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleValue1 时在主标题右边显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleDefault 时不显示副标题,图标在左边显示
- */
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
- // 设置分割线对齐(注意:与tableview的 separatorInset、layoutMargins 属性同时设置才有效)
- cell.separatorInset = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
- cell.layoutMargins = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
- // 选中时的状态
- cell.selectionStyle = UITableViewCellSelectionStyleGray;
- // 设置自定义事件图标(在右侧显示。注意:accessoryType 与 accessoryView 不能同时设置)
- UIImageView *accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cellImage"]];
- accessoryView.frame = CGRectMake(0.0, 0.0, 20.0, 20.0);
- cell.accessoryView = accessoryView;
- // 设置系统副件图标(在右侧显示。注意:accessoryType 与 accessoryView 不能同时设置)
- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- }
- NSDictionary *dict = self.mainArray[indexPath.section];
- NSArray *array = [dict objectForKey:@"array"];
- NSString *text = [array objectAtIndex:indexPath.row];
- // 设置cell中的图标
- cell.imageView.image = [UIImage imageNamed:@"cellImage"];
- // 设置cell中的主标题
- cell.textLabel.text = text;
- // 设置cell中的副标题,在主标题下面显示
- /*
- 注意:
- 实例化时样式为 UITableViewCellStyleSubtitle 时在主标题下面显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleSubtitle 时在主标题下面显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleValue1 时在主标题右边显示,图标在左边显示
- 实例化时样式为 UITableViewCellStyleDefault 时不显示副标题,图标在左边显示
- */
- cell.detailTextLabel.text = @"ios learning";
- return cell;
- }
- //- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- //{
- // // 每个section中的页眉视图的标题
- // // 设置后不能再设置 - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
- //
- // NSString *title = [NSString stringWithFormat:@"header section %@", @(section)];
- // return title;
- //}
- //
- //- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
- //{
- // // 每个section中的页脚视图的标题
- // // 设置后不能再设置 - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
- //
- // NSString *title = [NSString stringWithFormat:@"footer section %@", @(section)];
- // return title;
- //}
- // UITableViewDelegate
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- // 每个section中每个row的视图UITableViewCell的高度。默认是44.0
- return 44.0;
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
- {
- // 每个section中页眉的高度
- return 50.0;
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
- {
- // 每个section中页脚的高度
- return 20.0;
- }
- - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
- {
- // 设置每个section的页眉视图
- // 设置后不能再设置 - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- NSDictionary *dict = self.mainArray[section];
- NSString *title = [dict objectForKey:@"title"];
- // 未复用
- // UIButton *view = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 50.0)];
- // view.backgroundColor = [UIColor brownColor];
- // [view setTitle:title forState:UIControlStateNormal];
- // [view setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
- //
- // view.tag = 1000 + section;
- // [view addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
- //
- // return view;
- // 复用
- static NSString *const identifier = @"headerview";
- UITableViewHeaderFooterView *headerview = [tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier];
- if (headerview == nil)
- {
- headerview = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:identifier];
- UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10.0, 10.0, (CGRectGetWidth(self.view.bounds) - 10.0 * 2), 30.0)];
- button.backgroundColor = [UIColor brownColor];
- [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
- button.tag = 2000;
- // button.tag = 1000 + section;
- [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
- [headerview.contentView addSubview:button];
- }
- headerview.contentView.tag = 1000 + section;
- NSLog(@"headerview.tag = %@", @(headerview.tag));
- UIButton *button = (UIButton *)[headerview.contentView viewWithTag:2000];
- [button setTitle:title forState:UIControlStateNormal];
- return headerview;
- }
- - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
- {
- // 设置每个section的页脚视图
- // 设置后不能再设置 - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
- NSDictionary *dict = self.mainArray[section];
- NSString *title = [dict objectForKey:@"title"];
- // 未复用
- // UILabel *view = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 20.0)];
- // view.backgroundColor = [UIColor yellowColor];
- // view.text = title;
- //
- // return view;
- // 复用
- static NSString *const identifier = @"footerview";
- UITableViewHeaderFooterView *footerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier];
- if (footerView == nil)
- {
- footerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:identifier];
- UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, (CGRectGetWidth(self.view.bounds) - 10.0 * 2), 20.0)];
- label.backgroundColor = [UIColor greenColor];
- label.tag = 2000;
- [footerView.contentView addSubview:label];
- }
- UILabel *label = (UILabel *)[footerView.contentView viewWithTag:2000];
- label.text = title;
- return footerView;
- }
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- {
- // UITableViewCell单元格选中点击
- // 取消高亮选中状态
- [tableView deselectRowAtIndexPath:indexPath animated:YES];
- NSLog(@"你点击了 第 %@ 个section中的第 %@ 个row", @(indexPath.section + 1), @(indexPath.row + 1));
- }
- // 响应方法 用于展开,或折叠section
- - (void)buttonClick:(UIButton *)button
- {
- // NSInteger section = button.tag - 1000;
- UIView *superview = button.superview;
- NSInteger tagSuperview = superview.tag;
- NSInteger section = tagSuperview - 1000;
- NSNumber *openNumber = self.boolArray[section];
- if (openNumber.intValue == 1)
- {
- [self.boolArray replaceObjectAtIndex:section withObject:@(0)];
- }
- else
- {
- [self.boolArray replaceObjectAtIndex:section withObject:@(1)];
- }
- // 重新刷新数据
- // 方法1 刷新全总数据
- // [self.tableview reloadData];
- // 方法2 只刷新改变的secton
- NSIndexSet *reloadIndexSet = [NSIndexSet indexSetWithIndex:section];
- [self.tableview reloadSections:reloadIndexSet withRowAnimation:UITableViewRowAnimationNone];
- }