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];
}
这篇博客详细介绍了UITableView的使用,包括其作为UIScrollView子类的滚动特性、设置UITableViewStyle的注意事项、必须实现的UITableViewDelegate和UITableViewDataSource代理方法。特别强调了复用技术,如UITableViewCell的复用以及section页眉和页脚的复用。同时提到了section页眉视图的点击效果实现,指出在设置title与view时要避免冲突。
&spm=1001.2101.3001.5002&articleId=51695322&d=1&t=3&u=403e192829c3456e9dae7d6b7b08abe0)
594

被折叠的 条评论
为什么被折叠?



