iOS开发 - 处理不等高TableViewCell的招术

课题一:如何计算Cell高度

方案一:直接法(面向对象)

嗯!Cell也是一样的,想知道cell到底有多高?直接问Cell本人就好了。直接法,就是把数据布局到Cell上,然后拿到Cell最底部控件的MaxY值。

  • 第一步:创建Cell并正确设置约束,使文字区域高度能够根据文字内容多少自动调整


    第一步 - 添加好约束.gif
  • 第二步:再给这个Cell添加点别的东东,就叫这个东东BottomCub了。为Cub添加好约束。


    第二步 - 随便添加点什么.gif
  • 第三步:为这个Cell写一个返回Cell高度 - 也就是BottomCub最大Y值的方法

#import "TestCell.h"

@interface TestCell ()
@property (strong, nonatomic) IBOutlet UILabel *longLabel;
@property (strong, nonatomic) IBOutlet UIView *bottomCub;
@end

@implementation TestCell

//  Cell的构造方法
+ (instancetype)creatWithTitle :(NSString *)title inTableView :(UITableView *)tableView
{
    TestCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(self)];
    if (!cell) {
        cell = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:kNilOptions].lastObject;
    }
    cell.longLabel.text = title;
    return cell;
}

/**
 *  拿到bottomCub的最大Y值并返回
 */
- (CGFloat)cellHeight
{
    [self layoutIfNeeded];    //  一定要强制布局下,否则拿到的高度不准确
    return CGRectGetMaxY(self.bottomCub.frame);
}

@end
  • 第四步:在代理方法中设置Cell高度
    *注意:计算Cell高度的过程,一定不要放在heightForRow代理方法中!这一点在后文中将会有所提及。
#import "AskCellViewController.h"
#import "TestCell.h"

@interface AskCellViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (strong, nonatomic) UITableView *tableView;

/** 测试数据 - Cell中文字内容数组*/
@property(copy,nonatomic) NSArray *testTitleArray;

@end

@implementation AskCellViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.tableView];

    self.tableView.frame = self.view.bounds;
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.tableFooterView = [[UIView alloc] init];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TestCell *cell = [TestCell creatWithTitle:self.testTitleArray[indexPath.row] inTableView:tableView];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//  *注意:计算Cell高度的过程,一定不要放在此代理方法中!这一点在后文中将会有所提及,此处仅为演示方便
    CGFloat cellHeight = [[TestCell creatWithTitle:self.testTitleArray[indexPath.row] inTableView:tableView] cellHeight];
    NSLog(@"%f",cellHeight);
    return cellHeight;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.testTitleArray.count;
}
#pragma mark - Lazy
- (UITableView *)tableView
{
    if (!_tableView) {
        _tableView = [[UITableView alloc] init];
    }
    return _tableView;
}


- (NSArray *)testTitleArray
{
    return @[@"我是第一个Cell",@"我是第二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二个Cell",@"我是第三个Cell"];
}

@end
  • 效果

    动态设定Cell高度结果.gif

方案二:自己算(面向过程)

想知道妹纸爱你有多深?自己来算算看~

通常情况下,Cell之所以不等高,是因为Cell内部文字区域的高度会根据文字数量动态变化,图片区域的高度会根据图片数量而自动变化。也就是说,只要知道文字区域的高度、图片区域的高度,就可以硬生生计算出Cell的高度了。

  • 第一步:硬生生的将每个Cell的高度算出来,并保存在一个数组中
  • 第二步:heightForRow方法中返回相应的CellHeight
#import "CalculatorViewController.h"
#import "TestCell.h"

@interface CalculatorViewController ()<UITableViewDelegate,UITableViewDataSource>

@property (strong, nonatomic) UITableView *tableView;
/** 测试数据 - Cell中文字内容数组*/
@property(copy,nonatomic) NSArray *testTitleArray;
/** 用来存Cell高度的数组*/
@property(copy,nonatomic) NSArray *cellHeightArray;

@end

@implementation CalculatorViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.tableView];

    self.tableView.frame = self.view.bounds;
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.tableFooterView = [[UIView alloc] init];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TestCell *cell = [TestCell creatWithTitle:self.testTitleArray[indexPath.row] inTableView:tableView];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat cellHeight = [self.cellHeightArray[indexPath.row] floatValue];
    return cellHeight;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.testTitleArray.count;
}
#pragma mark - Lazy
- (UITableView *)tableView
{
    if (!_tableView) {
        _tableView = [[UITableView alloc] init];
    }
    return _tableView;
}
- (NSArray *)testTitleArray
{
    return @[@"我是第一个Cell",@"我是第二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二二个Cell",@"我是第三个Cell"];
}
- (NSArray *)cellHeightArray
{
    NSMutableArray *cellHeightTMPArray = [@[] mutableCopy];
    //  开始硬生生的计算每一个Cell高度
    for (NSString *string in self.testTitleArray) {
        CGFloat cellHeight = 0;
        //  一个Cell由两部分组成 - 高度自动调整的Label & bottomCub
        //  bottomCub高度是确定的 - 120,Label和bottomCub之间的间距是确定的 - 8
        static CGFloat bottomCubHeight = 120;
        static CGFloat bottomMargin = 8;
        //  计算Label的高度 - 其实就是计算Lable中的String的总高度
            //  1. 拿到将要放入Lable的String
        NSString *stringForLabel = string;
        //  2. 根据文字内容、字体(固定值)、文字区域最大宽度计算String总高度
        static CGFloat fontSize = 17;
        CGFloat labelHeight = [stringForLabel sizeWithFont:[UIFont systemFontOfSize:fontSize] constrainedToSize:CGSizeMake(self.tableView.frame.size.width, CGFLOAT_MAX)].height;
            //  3. 拿到了总高度,放入数组
        cellHeight = labelHeight + bottomMargin + bottomCubHeight;

        [cellHeightTMPArray addObject:@(cellHeight)];
    }
    return cellHeightTMPArray;
}
@end
  • 效果
    ummmm就不给效果图了哦,和上一张是一样一样的~

方案三:利用iOS8新特性

想知道妹纸爱你有多深?知道这个干嘛,直接通过iOS8,让妹纸爱上你不就好啦~

其实,iOS8已经提供了直接通过XIB让Cell高度自适应的方法了,只要简单拖拖线,根本木有必要计算Cell高度,就可以搞定不等高Cell

  • 第一步:设置tableView的估算Cell高度&rowHeight值为自动计算模式
- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.estimatedRowHeight = 100;  //  随便设个不那么离谱的值
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  • 第二步:为Cell中最下面的View设置约束 - 除了要定高、定宽、左上角粘着Label外,还要设置bottom距contentView的bottom间距为固定值,如0

bottomCub约束的添加方式.gif
  • 第三步:一定要注意 - 不能实现heightForRow代理方法!!!不能实现heightForRow代理方法!!!不能实现heightForRow代理方法!!!重要的事情说三遍...
    - (CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath
    {
    return 1000;


    iOS8新特性实现Cell高度的自适应.gif
  • 效果:一样杠杠滴~

课题二:在哪计算Cell高度

方案一:在heightForRow代理方法中计算

  • 示例代码:见课题一方案一
  • 说明:在这里进行计算是非常糟糕的选择,因为系统调用heightForRow方法非常频繁 感兴趣的小伙伴可以打印测试下...在这里进行计算,意味着系统每调用一次heightForRow方法,就会执行一次高度计算...好可怕有木有
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值