UITableView

版权声明:未经本人允许,禁止转载.

1. TableView初始化

UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
  • 1.UITableView有两种风格:UITableViewStylePlain(普通样式)和UITableViewStyleGrouped(分组样式)
  • 2.UITableView显示数据需要设置数据源dataSource,执行操作需要设置代理delegate

2. TableView的属性和方法

1. 设置高度

  1. 设置cell,分区头(header),分区尾(footer)的高度
    //属性设置 设置表中所有的对象
    tableView.rowHeight = 50;
    tableView.sectionHeaderHeight = 40;
    tableView.sectionFooterHeight = 40;
    //delegate
    //返回指定indexPath的Row的高度时调用
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 50;
    }
    //返回指定分区(section)的Header的高度时调用
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 40;
    }
    //返回指定分区(section)的Footer的高度时调用
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 40;
    }
  2. 估算cell,分区头(header),分区尾(footer)的高度 (iOS 7 or later)
    //属性设置 设置表中所有的对象
    tableView.estimatedRowHeight = 50;
    tableView.estimatedSectionHeaderHeight = 40;
    tableView.estimatedSectionFooterHeight = 40;
    //delegate
    //估算指定indexPath的Row的高度调用
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 50;
    }
    //估算指定分区(section)的Header的高度时调用
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section {
    return 40;
    }
    //估算指定分区(section)的Footer的高度时调用
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section {
    return 40;
    }

估算高度(estimatedHeight)是为了加快tableView的加载速度,设置估算高度后,conteSize.height根据 cell的估算值 * cell的个数 计算,contentSize会随着滚动从估算慢慢替换成真实高度,结果会导致滚动条的大小处于不稳定状态,甚至出现"跳跃".

  1. 常量UITableViewAutomaticDimension (iOS 5 or later)
    //cell(iOS 8 or later)
    tableView.estimatedRowHeight = 44.0
    tableView.rowHeight = UITableViewAutomaticDimension

在UITableViewStyleGrouped情况下,动态计算TableView的headerTitle和FooterTitle的高度
在iOS 8之后,可以动态计算cell的高度,要求必须使用autoLayout

2.设置cell的分割线(separator)

  1. 设置分割线缩进
    属性: separatorInset (iOS 7 or later) 在代码情况下正常
    tableView.separatorInset = UIEdgeInsetsMake(0, 30, 0, 50);
  2. 设置分割线类型
    属性: separatorStyle 为枚举类型
    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    enum {
    UITableViewCellSeparatorStyleNone,//没分割线
    UITableViewCellSeparatorStyleSingleLine,//单线(默认)
    UITableViewCellSeparatorStyleSingleLineEtched//只支持UITableViewStyleGrouped,不过看起来没什么效果
    }
  3. 设置分割线颜色
    属性: separatorColor
    //默认为灰色
    tableView.separatorColor = [UIColor cyanColor];
  4. 设置分割线模糊化(毛玻璃效果)
    属性: separatorEffect (iOS 8 or later)
    分割线会根据背景色模糊化
    UIImageView *bg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"launchImage.png"]];
    tableView.backgroundView = bg;
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
    tableView.separatorEffect = vibrancyEffect;

3.设置分区索引栏 (SectionIndex)

  1. 设置索引栏显示所需最小cell的数量
    属性: sectionIndexMinimumDisplayRowCount
    //cell个数 >= 20 显示索引栏
    tableView.sectionIndexMinimumDisplayRowCount = 20;
  2. 设置索引栏字体颜色
    属性: sectionIndexColor (iOS 6 or later)
    tableView.sectionIndexColor = [UIColor redColor];
  3. 设置索引栏背景色
    属性: sectionIndexBackgroundColor (iOS 7 or later)
    tableView.sectionIndexBackgroundColor = [UIColor cyanColor];
  4. 设置索引栏点击时的背景色
    属性: sectionIndexTrackingBackgroundColor (iOS 6 or later)
    tableView.sectionIndexTrackingBackgroundColor = [UIColor blackColor];
  5. 设置索引栏内容
    数据源: - sectionIndexTitlesForTableView:
    返回索引数组,对应相应的分区
    - (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return @[@"0",@"1",@"2",@"3",@"10",@"20"];
    }
  6. 设置各个索引对应的分区
    数据源: - tableView:sectionForSectionIndexTitle:atIndex:
    通过title和index确定索引,返回该索引指定的分区
    - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    if ([title isEqualToString:@"10"]){
    return 0;
    }else if(index == 5) {
    return 1;
    }
    return index;
    }
  7. 刷新分区索引栏 (iOS 3.0 or later)
    调用方法: - reloadSectionIndexTitles
    [tableView reloadSectionIndexTitles];

4.设置背景View,表头,表尾

  1. 设置TableView背景的View
    一般用于设置背景图片等,会自适应大小
    属性: backgroundView (iOS 3.2 or later)
    UIImageView *bg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Image.png"]];
    tableView.backgroundView = bg;
  2. 设置表格的表头
    表格最上部添加辅助的View,不会悬停
    属性: tableHeaderView
    tableView.tableHeaderView = [self tableHeaderView];
    - (UIView *)tableHeaderView {
    UILabel *headerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 80)];
    headerView.backgroundColor = [UIColor orangeColor];
    headerView.text = @"表头";
    headerView.textAlignment = NSTextAlignmentCenter;
    return headerView;
    }
  3. 设置表格的表尾
    表格最下部添加辅助View,不会悬停
    属性: tableFooterView
    tableView.tableFooterView = [self tableFooterView];
    - (UIView *)tableFooterView {
    UILabel *footerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 80)];
    footerView.backgroundColor = [UIColor orangeColor];
    footerView.text = @"表尾";
    footerView.textAlignment = NSTextAlignmentCenter;
    return footerView;
    }

5.设置分区头(header)和分区尾(footer)

  1. 注册HeaderFooterView (iOS 6.0 or later)
    注册Xib
    调用方法: - registerNib:forHeaderFooterViewReuseIdentifier:
    [tableView registerNib:[UINib nibWithNibName:@"TableHeaderFooterView" bundle:nil] forHeaderFooterViewReuseIdentifier:footerView];
    注册Class
    调用方法: - registerClass:forHeaderFooterViewReuseIdentifier:
    [tableView registerClass:[TableHeaderFooterView class] forHeaderFooterViewReuseIdentifier:headerView];
  2. 获取重用的HeaderFooterView (iOS 6.0 or later)
    调用方法: - dequeueReusableHeaderFooterViewWithIdentifier:
    TableHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerView];
  3. 创建HeaderFooterView
    获取指定分区(section)的HeaderView时调用
    代理: - tableView:viewForHeaderInSection:
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    TableHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerView];
    view.textLabel.text = [NSString stringWithFormat:@"第%ld分区头",section];
    return view;
    }
    获取指定分区(section)的FooterView时调用
    代理: - tableView:viewForFooterInSection:
    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    TableHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:footerView];
    view.name.text = [NSString stringWithFormat:@"第%ld分区尾",section];
    return view;
    }
  4. 设置HeaderFooterTitle (HeaderFooterView优先级大于title)
    设置指定分区(section)的title (HeaderTitle)
    数据源: - tableView:titleForHeaderInSection:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"第%ld分区头",section];
    }
    设置指定分区(section)的title (FooterTitle)
    数据源: - tableView:titleForFooterInSection:
    - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"第%ld分区尾",section];
    }
  5. 设置修改指定分区(section)的HeaderFooterView (iOS 6.0 or later)
    HeaderView将要显示时调用
    代理: - tableView:willDisplayHeaderView:forSection:
    FooterView将要显示时调用
    代理: - tableView:willDisplayFooterView:forSection:
    //headerView将要出现
    - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    TableHeaderFooterView *header = (TableHeaderFooterView *)view;
    header.contentView.backgroundColor = [UIColor yellowColor];
    }
    //footerView将要出现
    - (void)tableView:(UITableView *)tableView willDisplayFooterView:(nonnull UIView *)view forSection:(NSInteger)section {
    if (section == 0) {
    TableHeaderFooterView *footer = (TableHeaderFooterView *)view;
    footer.bgView.backgroundColor = [UIColor greenColor];
    }
    }
    HeaderView已经消失时调用
    代理: - tableView:didEndDisplayingHeaderView:forSection:
    FooterView已经消失时调用
    代理: - tableView:didEndDisplayingFooterView:forSection:
    //headerView已经消失
    - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(nonnull UIView *)view forSection:(NSInteger)section {
    TableHeaderFooterView *header = (TableHeaderFooterView *)view;
    header.textLabel.textAlignment = NSTextAlignmentRight;
    }
    //footerView已经消失
    - (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(nonnull UIView *)view forSection:(NSInteger)section {
    if (section == 1) {
    TableHeaderFooterView *footer = (TableHeaderFooterView *)view;
    footer.bgView.backgroundColor = [UIColor orangeColor];
    }
    }
  6. 返回HeaderFooterView (iOS 6.0 or later)
    返回指定分区(section)的HeaderView
    调用方法: - headerViewForSection:
    TableHeaderFooterView *headerView = (TableHeaderFooterView *)[tableView headerViewForSection:indexPath.section];
    headerView.contentView.backgroundColor = [UIColor blackColor];
    返回指定分区(section)的FooterView
    调用方法: - footerViewForSection:
    TableHeaderFooterView *footerView = (TableHeaderFooterView *)[tableView footerViewForSection:indexPath.section];
    footerView.bgView.backgroundColor = [UIColor grayColor];
  7. 返回HeaderFooterView的大小Rect
    返回指定分区(section)的大小(HeaderRect)
    调用方法: - rectForHeaderInSection:
    CGRect headerRect = [tableView rectForHeaderInSection:indexPath.section];
    NSLog(@"分区头大小 = %@",NSStringFromCGRect(headerRect));
    返回指定分区(section)的大小(FooterRect)
    调用方法: - rectForFooterInSection:
    CGRect footerRect = [tableView rectForFooterInSection:indexPath.section];
    NSLog(@"分区尾大小 = %@",NSStringFromCGRect(footerRect));

6.设置分区(section)

  1. 设置表格分区数
    数据源: - numberOfSectionsInTableView:
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 4;
    }
  2. 返回表格分区数
    属性:numberOfSections
    NSInteger number = tableView.numberOfSections;
  3. 返回指定分区(section)的大小
    调用方法: - rectForSection:
    CGRect sectionRect = [tableView rectForSection:indexPath.section];
    NSLog(@"分区大小 = %@",NSStringFromCGRect(sectionRect));
  4. 设置动画块
    调用方法: - beginUpdates 和 - endUpdates
    两个方法成对使用,表示一个动画块.在动画块中可以对表格执行多个连续的插入,删除,移动等操作
    [self.tableView beginUpdates];
    [self.tableView insertSections:set withRowAnimation:UITableViewRowAnimationLeft];
    [self.tableView deleteSections:set withRowAnimation:UITableViewRowAnimationTop];
    [self.tableView endUpdates];
  5. 通过指定的动画,在指定位置插入分区(1个或多个)
    调用方法 - insertSections:withRowAnimation: 插入分区时,需要修改分区数目
    - (void)insertSection {
    NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)];
    self.sectionNum += 3;
    [self.tableView insertSections:set withRowAnimation:UITableViewRowAnimationLeft];
    }
  6. 通过指定的动画,删除指定的分区(1个或多个)
    调用方法 - deleteSections:withRowAnimation: 删除分区时,需要修改分区数目
    - (void)deleteSection {
    NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
    if (self.sectionNum >= 2) {
    self.sectionNum -= 2;
    [self.tableView deleteSections:set withRowAnimation:UITableViewRowAnimationTop];
    }
    }
  7. 通过指定的动画,刷新指定的分区(1个或多个)
    调用方法 - reloadSections:withRowAnimation:
    - (void)reloadSection {
    NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
    [self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationTop];
    }
  8. 将指定分区移动到另一个位置 (iOS 5.0 or later)
    调用方法 - moveSection:toSection:
    - (void)moveSection {
    [self.tableView moveSection:1 toSection:2];
    }

7.设置TableViewCell

  1. 注册cell
    注册Xib (iOS 5.0 or later)
    调用方法 - registerNib:forCellReuseIdentifier:
    [tableView registerNib:[UINib nibWithNibName:@"TableViewCell" bundle:nil] forCellReuseIdentifier:tableViewCell2];
    注册Class (iOS 6.0 or later)
    调用方法 - registerClass:forCellReuseIdentifier:
    [tableView registerClass:[TableViewCell class] forCellReuseIdentifier:tableViewCell1];
  2. 返回重用的cell
    方法1: - dequeueReusableCellWithIdentifier: 适用于cell为空时申请空间
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableViewCell1];
    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableViewCell1];
    }
    方法2: - dequeueReusableCellWithIdentifier:forIndexPath: (iOS 6.0 or later) 适用于注册的cell或storyboard中的cell
    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
  3. 设置指定indexPath的cell
    必须实现的方法
    数据源: - tableView:cellForRowAtIndexPath:
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *identifier = (indexPath.section < 2) ? tableViewCell1:tableViewCell2;
    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    //前两个分区为Cell1
    if (indexPath.section < 2) {
    cell.textLabel.text = [NSString stringWithFormat:@"test %ld %ld",indexPath.section,indexPath.row];
    }else {//其余的为Cell2
    cell.name.text = [NSString stringWithFormat:@"%ld",indexPath.section];
    cell.title.text = [NSString stringWithFormat:@"%ld",indexPath.row];
    }
    cell.backgroundColor = [UIColor clearColor];
    return cell;
    }
  4. 修改指定indexPath的cell
    cell将要显示时调用(willDisplay)
    代理: - tableView:willDisplayCell:forRowAtIndexPath:
    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) {
    cell.contentView.backgroundColor = [UIColor purpleColor];
    }
    }
    cell已经消失时调用 (iOS 6.0 or later)
    代理: - tableView:didEndDisplayingCell:forRowAtIndexPath:
    - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 2) {
    cell.contentView.backgroundColor = [UIColor blueColor];
    }
    }
  5. 返回指定indexPath对应的cell
    调用方法: - cellForRowAtIndexPath:
    TableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.contentView.backgroundColor = [UIColor greenColor];
  6. 返回指定indexPath的row的Rect
    调用方法: - rectForRowAtIndexPath:
    CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
    NSLog(@"cell大小 = %@",NSStringFromCGRect(cellRect));
  7. 返回可见区域内cell数组
    属性:visibleCells
    NSArray *cellArr = tableView.visibleCells;
    NSLog(@"可见cell数组:%@",cellar);
  8. 设置指定分区(section)中row的个数
    必须实现的方法
    数据源: - tableView:numberOfRowsInSection:
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.rowNum;
    }
  9. 返回指定分区(section)中row的个数
    调用方法: - numberOfRowsInSection:
    NSInteger rowNum = [tableView numberOfRowsInSection:indexPath.section];
    NSLog(@"该分区row的个数 = %ld",rowNum);

8.NSIndexPath (UITableView)

  1. indexPath包括分区(section)和行(row)
    初始化: + indexPathForRow:inSection:
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:2 inSection:0];
    NSLog(@"section = %ld, row = %ld",indexPath.section,indexPath.row);
  2. 返回指定点所在row对应的indexPath
    调用方法: - indexPathForRowAtPoint:
    NSIndexPath *indexPath2 = [tableView indexPathForRowAtPoint:cellRect.origin];
    NSLog(@"section = %ld, row = %ld",indexPath2.section,indexPath2.row);
  3. 返回指定cell对应的indexPath
    调用方法: - indexPathForCell:
    NSIndexPath *indexPath3 = [tableView indexPathForCell:cell];
    NSLog(@"section = %ld, row = %ld",indexPath3.section,indexPath3.row);
  4. 返回选中row对应的indexPath
    属性: - indexPathForSelectedRow
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    NSLog(@"section = %ld, row = %ld",indexPath.section,indexPath.row);
  5. 返回指定区域(Rect)内所有rows对应的indexPath数组
    调用方法: - indexPathsForRowsInRect:
    NSArray *indexPathArr1 = [self.tableView indexPathsForRowsInRect:self.view.bounds];
    NSLog(@"%@",indexPathArr1);
  6. 返回表格中所有可见行(rows)对应的indexPath数组
    属性: indexPathsForVisibleRows
    NSArray *indexPathArr2 = [self.tableView indexPathsForVisibleRows];
    NSLog(@"%@",indexPathArr2);
  7. 返回表格中所有选中行(rows)对应的indexPath数组
    属性: indexPathsForSelectedRows (iOS 5.0 or later)
    NSArray *indexPathArr3 = self.tableView.indexPathsForSelectedRows;
    NSLog(@"%@",indexPathArr3);

9.选择(Selecte)和滚动(Scroll)

  1. 设置是否允许选择(非编辑状态下) 默认Yes
    属性: allowsSelection (iOS 3.0 or later)
    tableView.allowsSelection = YES;
  2. 设置表格编辑状态下是否允许选择 默认为NO
    属性: allowsSelectionDuringEditing
    tableView.allowsSelectionDuringEditing = YES;
  3. 设置表格是否允许多选(非编辑状态下) 默认为NO
    属性: allowsMultipleSelection (iOS 5.0 or later)
    tableView.allowsMultipleSelection = YES;
  4. 设置表格编辑状态下是否允许多选 默认为NO
    属性: allowsMultipleSelectionDuringEditing (iOS 5.0 or later)
    tableView.allowsMultipleSelectionDuringEditing = YES;
  5. 设置表格选中指定indexPath的row
    调用方法: - selectRowAtIndexPath:animated:scrollPosition:
    最后一个参数决定选定cell的显示位置
    [tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
  6. 设置表格中指定indexPath的row的选中取消
    调用方法: - deselectRowAtIndexPath:animated:
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
  7. 用户将要选中某行时触发
    可以指定一些indexPath不能选择,或选择不同的row都是选择同一个indexPath:
    代理: - tableView:willSelectRowAtIndexPath:
    //指定row == 0不能选择
    - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) {
    return nil;
    }
    return indexPath;
    }
  8. 用户完成选中某行时触发
    可以做选中之后的操作
    代理: - tableView:didSelectRowAtIndexPath:
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //取消选择状态
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
  9. 用户将要取消选中行时触发
    代理: - tableView:willDeselectRowAtIndexPath: (iOS 3.0 or later)
    //指定row == 1 不能取消选中
    - (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 1) {
    return nil;
    }
    return indexPath;
    }
  10. 用户完成取消选中行时触发
    做一些取消选中后的操作
    代理: - tableView:didDeselectRowAtIndexPath: (iOS 3.0 or later)
    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    TableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.contentView.backgroundColor = [UIColor orangeColor];
    }

推荐阅读更多精彩内容