IOS控件布局之UITableView使用

前言:

    UITableView在iOS中的地位就类似Android的ListView、RecyclerView,是使用频率非常重要的一个控件类,所以很必要了解它的一些基本使用,2016春节放假前夕我还是觉得有必要去学习一下这个控件。

UITableView的初始化及一些常用属性设置

1.)初始化

    //第一种方式
    UITableView *tableView =[[UITableView alloc]init];
    //第二种方式 指定大小位置
    UITableView *tableView =[[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) ];
    //第三种方式 指定大小位置 并设置style
    UITableView *tableView =[[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStyleGrouped];

关于style UITableViewStyleGrouped、UITableViewStylePlain

  • grouped的sectionHeader,sectionFooter的背景色默认跟tableview的背景色一样,plain是透明的
  • grouped的sectionHeader不会悬浮,plain的是悬浮的
  • plain会出现多余的分割线,grouped不会
  • grouped某一行的上线边缘默认会有分割线

2.)一些常规参数设置

// 设置背景
    mTableView.backgroundColor = [UIColor whiteColor];
    
    // 设置分割线的类型
    mTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    
    // 设置分割线颜色
    mTableView.separatorColor = [UIColor greenColor];
    
    // 设置分割线的位置
    mTableView.separatorInset = UIEdgeInsetsMake(0, 20, 0, 20);
    
    //以下三组高度的设置 我们一般都是通过UITableViewDelegate来设置
    //修改tableView的行高
    mTableView.rowHeight = 72;
    //组头组尾的高
    mTableView.sectionHeaderHeight = 30;
    mTableView.sectionFooterHeight = 0.0001f;
    
    //设置UITableView的headerView
    UIView *headerView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 30)];
    headerView.backgroundColor=[UIColor orangeColor];
    mTableView.tableHeaderView=headerView;
    
    //设置UITableView的footerView
    UIView *footerView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 30)];
    footerView.backgroundColor=[UIColor orangeColor];
    mTableView.tableFooterView=footerView;

3.)添加数据源和代理

    //添加数据源
    mTableView.dataSource=self;
    //添加代理
    mTableView.delegate=self;

优先看下dataSource UITableViewDataSource用于控制数据源

// 数据源方法
@protocol UITableViewDataSource<NSObject>

@required // 必须实现的方法

// 每个section有多少rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

// 设置cell的详情,需要用到的重要概念,cell的重用机制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

@optional //可选的实现方法

// 设置section的数量,默认为1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

// section由两部分组成,header和footer,分别设置各自需要展示的字符串,也可以自定义显示的样式,需要用到其他的方法
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;

// Editing 编辑需要用到的方法
// 哪些row可以被编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;

// Moving/reordering  移动
// 哪些row可以被移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;

// Index
// 设置索引
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView __TVOS_PROHIBITED;  // return list of section titles to display in section index view (e.g. "ABCD...Z#")
// 设置索引的响应
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index __TVOS_PROHIBITED;  // tell table which section corresponds to section title/index (e.g. "B",1))

// Data manipulation - insert and delete support 删除和插入实现的方法
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

// Data manipulation - reorder / moving support 移动实现的方法
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

@end

接下来看下delegate UITableViewDelegate 用于控制数据在UI上的高度设置事件触发等

@protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>

@optional // 可选的常用的方法

// 设置对应的cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
//设置对应的分组headerView高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
//设置对应的分组的footerView高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

// 自定义headerView
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
//自定义footerView
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

// 设置编辑的样式
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;

// 移动or排序
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;

@end

特别注意:

  IOS不允许Header和Footer为0,所以我们一般想要设置为0的时候可以协议无限接近0的值来解决这个问题

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 0.0001f;
}

4.)UITableViewCell重用机制

    UITableView继承自UIScrollView,无限制的向里面添加UITableViewCell,势必导致内存吃紧,所以iOS里也有向Android的ListView、RecyclerView一样有cell的重用机制,我们先看如何在UITableViewDataSource的- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;函数中实现cell重用的

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1.创建重用标识符
    static NSString *identifier = @"LcjViewCell";
    
    // 2.去重用队列中根据标识符取可重用的cell
    
    LcjViewCell *lcjViewCell=  [tableView dequeueReusableCellWithIdentifier:identifier];
    
    // 3.判断是否获取到可重用的cell(最后要空间释放)
    
    if (!lcjViewCell) {
        lcjViewCell = [[LcjViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        lcjViewCell.selectionStyle = UITableViewCellSelectionStyleNone;
    }
    lcjViewCell.nameLabel.text=[NSString stringWithFormat:@"第%ld个",(long)indexPath.row];
    lcjViewCell.headView.image=[UIImage imageNamed:@"red_money_small_big"];
    
    return lcjViewCell;
    
}

上面采用的如果cell不存在就重新创建的方式,也可以采用提前注册的方式 

  [mTableView registerClass:[LcjViewCell class] forCellReuseIdentifier:@"LcjViewCell"];

然后UITableViewDataSource的调用方式和上面大致相同

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //1.创建重用标识符
    static NSString *identifier = @"LcjViewCell";
    
    // 2.去重用队列中根据标识符取可重用的cell
    
    LcjViewCell *lcjViewCell=  [tableView dequeueReusableCellWithIdentifier:identifier];
    // 3.判断是否获取到可重用的cell(最后要空间释放)
//    
//    if (!lcjViewCell) {
//        lcjViewCell = [[LcjViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
//    }
    lcjViewCell.selectionStyle = UITableViewCellSelectionStyleNone;
    lcjViewCell.nameLabel.text=[NSString stringWithFormat:@"第%ld个",(long)indexPath.row];
    lcjViewCell.headView.image=[UIImage imageNamed:@"red_money_small_big"];
return lcjViewCell; }

除了对UITableViewCell提供了复用机制,对分组的headerView和footerView也提供了复用机制,使用方式如下:

- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerViewId = @"HeaderView";
    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerViewId];
    if (headerView==nil) {
        headerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:headerViewId];
        headerView.contentView.backgroundColor=[UIColor grayColor];
    }
    headerView.textLabel.text=[NSString stringWithFormat:@"第%ld组列表",(long)section+1];
    return headerView;
}

5.)自定义UITableViewCell实现

首先定义一个Cell继承UITableViewCell

#import <UIKit/UIKit.h>

@interface LcjViewCell : UITableViewCell

@property (nonatomic,strong)UILabel *nameLabel;//名字label

@property (nonatomic,strong)UIImageView *headView;//头像ImageView


@end

接下来看下LcjViewCell.m的实现

#import "LcjViewCell.h"

@implementation LcjViewCell

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        self.backgroundColor = [UIColor whiteColor];
        [self.contentView addSubview:self.headView];
        [_headView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.centerY.mas_equalTo(self.contentView.mas_centerY);
            make.size.mas_equalTo(CGSizeMake(60, 60));
        }];
        [self.contentView addSubview:self.nameLabel];
        [_nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(self.headView.mas_right).mas_equalTo(10);
            make.centerY.mas_equalTo(self.contentView.mas_centerY);
        }];
    }
    return self;
    
}

-(UILabel *)nameLabel
{
    
    if(_nameLabel == nil){
        _nameLabel =[[UILabel alloc]init];
        _nameLabel.textColor=[UIColor blackColor];
        _nameLabel.font=[UIFont systemFontOfSize:17];
        _nameLabel.textAlignment=NSTextAlignmentLeft;
    }
    
    return _nameLabel;
}

-(UIImageView *)headView
{
    
    if(_headView == nil){
        _headView=[[UIImageView alloc]init];
    }
    
    return _headView;
    
}
- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    // Configure the view for the selected state
}

@end

总结:

   大致学习了UITableView的基本使用,后续在继续使用中继续学习。

 

posted on 2017-01-20 11:41  总李写代码  阅读(802)  评论(0)    收藏  举报