iOSTableViewCell不等高的几种方法

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

直接法,就是把数据布局到Cell上,然后拿到Cell最底部控件的MaxY值。

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

添加好约束

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

随便添加点什么

第三步:为这个Cell写一个返回Cell高度 - 也就是BottomCub最大Y值的方法


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

#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

{

    //  强制布局之前,需要先手动设置下cell的真实宽度,以便于准确计算

    CGRect rect = self.frame;

    rect.size.width = [[UIScreen mainScreen] bounds].size.width;

    self.frame = rect;

    [self layoutIfNeeded];    //  一定要强制布局下,否则拿到的高度不准确

    return CGRectGetMaxY(self.bottomCub.frame);

}

@end

第四步:在代理方法中设置Cell高度

*注意:计算Cell高度的过程,一定不要放在heightForRow代理方法中!这一点在后文中将会有所提及。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

#import "AskCellViewController.h"

#import "TestCell.h"

@interface AskCellViewController ()

@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高度结果

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

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

注意注意注意:如果产品有可能会要求调整行距,切不可用此方法计算!

替代可选方案:


1

CGSize size = [cell.content sizeThatFits:CGSizeMake(cell.content.frame.size.width, MAXFLOAT)];

(注于:2016.1.28)

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

#import "CalculatorViewController.h"

#import "TestCell.h"

@interface CalculatorViewController ()

@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

效果

  • 就不给效果图了哦,和上一张是一样一样的~

方案三:利用iOS 8新特性

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

第一步:设置tableView的估算Cell高度&rowHeight值为自动计算模式


1

2

3

4

5

6

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.tableView.estimatedRowHeight = 100;  //  随便设个不那么离谱的值

    self.tableView.rowHeight = UITableViewAutomaticDimension;

}

第二步:为Cell中最下面的View设置约束 - 除了要定高、定宽、左上角粘着Label外,还要设置bottom距contentView的bottom间距为固定值,如0

bottomCub约束的添加方式

第三步:一定要注意 - 不能实现heightForRow代理方法!!!不能实现heightForRow代理方法!!!不能实现heightForRow代理方法!!!重要的事情说三遍...

iOS8新特性实现Cell高度的自适应

效果:一样杠杠滴~

课题二:在哪计算Cell高度

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

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

方案二:在请求到数据后马上计算

  • 示例代码:见课题一方案二
  • 说明:在这里进行计算相对于方案一来说进步了很多,在这里计算是不错的选择哦!

方案三:在cellForRow代理方法中算

  • 说明:其实,要隆重介绍的是方案三~
  • 思路:

1.既然想知道Cell的高度,那么一定是Cell自己最懂自己有多高啦(面向对象的思维)。

2.那么,在哪里能拿到Cell和Cell的高度呢? - 当然是CellForRow代理方法中啦!

3.但是,在CellForRow中拿到Cell高度后,如何传递给heightForRow代理方法呢? - 可以将Cell高度保存在一个数组中,或者保存在Cell对应的Model中~

4.但是,我们知道系统对tableView代理方法的调用顺序,是先调取heightForRow再调取cellForRow的呀,这意味着,我们在cellForRow方法中拿到cell高度之前,就需要设置heightForRow...怎么办?

a.解决方案:实现estimatedHeightForRow代理方法!

b.实现这个代理方法后,系统会先调取cellForRow,再调取heightForRow,而且实现这个代理方法之后,腰不酸了,腿不疼了,一口气上五楼也不费劲了~

  • 示例代码:可以参考下我之前的文章哦!传送门 - iOS项目实例:QQ聊天界面UI搭建
  • 注意:如果实现了estimatedHeightForRow代理方法,可能会造成tableView的ContentSize值不正确哦!所以,该方法请选择使用...

结论

  • 处理不等高TableViewCell,优先使用iOS8新特性(课题一方案三)
  • 不能使用iOS8新特性的情况下,优先选择课题一方案一+课题二方案三组合
  • 不能用上面两种,优先选择使用课题一方案一+课题二方案二组合~

补充

tableView的contentSize计算机制

实验方案

自定义一个tableView的子类,重写setContentSize方法,在该方法中打印contentSizeHeight,观察总结。

分两组:第一组实现estimatedHeightForRow方法,第二组不实现。

  • 第一组:section = 1 rowNumber = 5 | 估算行高10 | 实际行高100
  • 第二组:section = 1 rowNumber = 5 | 未实现估算行高 | 实际行高100

实验结果

第一组

实验一 - 1组5行|估算行高10|实际行高100|计算contentSize.gif

第二组

实验二 - 1组5行|不估算|实际行高100|计算contentSize.gif

实验结论

  • viewDidAppear方法中拿到的contentSize才是准确的contentSize
  • contentSize至少会设置3次,如果估算行高与实际行高不符,会再次设置contentSize

未解之谜

  • 通过打印我们可以看到,获取cell之前,诡异地对heighForRow方法遍历了三次...为什么是三次?
  • 为什么最少设置3次contentSize,不能只设置1次吗?
  • 能否把返回Cell的方法和heightForRow方法合并成一个代理方法?
时间: 2024-10-11 11:59:34

iOSTableViewCell不等高的几种方法的相关文章

android获取view宽高的几种方法

在onCreate方法中我们通过mView.getWidth()和mView.getHeight()获取到的view的宽高都是0,那么下面几种方法就可以在onCreate方法中获取到view的宽高. 1. int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED

placeholder右对齐的写法,兼容性比较高的一种方法

placeholder右对齐的写法,如果你不考虑移动端的话,完全可以使用text-align:right,不过如果考虑移动端的话,在有一些手机上,即使你写了text-align:right,placeholder也是左对齐的,经过百度后得出,http://stackoverflow.com/questions/6729837/text-align-right-only-for-placeholder,经过我的验证,这个方法完美无缺,特记录在册,以备后用!!! ::-webkit-input-pl

获取View的宽高的三种方法

来自为知笔记(Wiz)

iOS之处理不等高TableViewCell的几种方法

课题一:如何计算Cell高度 方案一:直接法(面向对象) 直接法,就是把数据布局到Cell上,然后拿到Cell最底部控件的MaxY值. 第一步:创建Cell并正确设置约束,使文字区域高度能够根据文字内容多少自动调整 添加好约束 第二步:再给这个Cell添加点别的东东,就叫这个东东BottomCub了.为Cub添加好约束. 随便添加点什么 第三步:为这个Cell写一个返回Cell高度 - 也就是BottomCub最大Y值的方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

CAD图纸转换成高质量的PDF文件,两种方法一步搞定哦

其实提到CAD,可能大家都大致的了解,CAD现在已经是建筑行业运用的非常广泛的一个设计软件了,其实CAD就是一种计算机辅助软件,可以高效的帮助我们进行图纸的绘制.我们一般在设计完图纸,可能定会转换格式,以至于可以方便的进行工作,PDF文件刚好有着很好的加密性,用起来方便快捷,真的是省时又省力.那接下来,就给大家看一下,怎么用两种方法,快速将CAD图纸文件转换成高质量的PDF文件吧. 第一步:首先,在你的电脑桌面上双击鼠标左键,开始运行CAD转换器.并在软件的下方界面中找到[CAD转PDF]功能属

WPF中三种方法得到当前屏幕的宽和高

原文:WPF中三种方法得到当前屏幕的宽和高 WPF程序中的单位是与设备无关的单位,每个单位是1/96英寸,如果电脑的DPI设置为96(每个英寸96个像素),那么此时每个WPF单位对应一个像素,不过如果电脑的DPI设备为120(每个英寸120个像素),那此时每个WPF单位对应应该是120/96=1.25个像素 一般在程序中我们常常需要得到当前屏幕的宽和高,常见做法有: 1.这两个方法可以返回当前屏幕选择的分辨率,该分辨率是以像素为单位,在DPI为96的情况下我们可以利用它们来做一些控件的定位,因为

如何选择高质量外链的五种方法

对于广大网站优化人员来讲,影响网站关键词排名的核心因素大家都不会陌生,最主要的三个要素就是网站原创内容,网站外链和网站內链.而在这三个因素中,网站外链始终是让我们头疼的问题,外链选择的好对网站能起到事半功倍的效果,反之如果我们发布的外链质量太低,不仅会浪费我们的时间,严重的还会对网站起到不好的作用,所以如何购买外链就成了我们网站优化人员最关心的问题.那么如何选择高质量外链呢?以下购链网小编就来讲下这个问题! 一.如何选择高质量外链之关键字选择. 至于如何选择关键字,互联网有很多站长朋友分享的方法

处理不等高TableViewCell

课题一:如何计算Cell高度 方案一:直接法(面向对象) 想知道妹纸爱你有多深?直接去问妹纸本人吧! 嗯!Cell也是一样的,想知道cell到底有多高?直接问Cell本人就好了.直接法,就是把数据布局到Cell上,然后拿到Cell最底部控件的MaxY值. 第一步:创建Cell并正确设置约束,使文字区域高度能够根据文字内容多少自动调整 第一步 - 添加好约束.gif 第二步:再给这个Cell添加点别的东东,就叫这个东东BottomCub了.为Cub添加好约束. 第二步 - 随便添加点什么.gif

不等高cell的tableView界面搭建

一.搭建界面 1.界面分析 分析界面的层次结构,分析界面应该用什么控件来搭建 2.界面层次结构 分析之后,我们可以把这个界面分为四个模块(topView middleView commentView bottomView) 这种复杂的界面,我们一般称为:不等高cell 3.界面搭建方式 分析发现,界面大部分是不能确定的(文字高度,有没有图片,评论) 所以我们采用纯代码的方法来搭建界面 但是复杂的界面我们划分过之后,有些小模块里面的内容是固定的 这些固定的小模块我们可以采用xib来搭建 4.有些模