【前言】

  在使用华尔街见闻 app 时,看到它的 tableVeiw 上的 cell 具有很好的展开与收缩功能。于是自己想了一下实现,感觉应该挺简单的,于是心痒痒写个 demo 实现一波。华尔街见闻 app 上的效果如下:

  

【本 demo 实现的效果图】

    

【思路】

  由它的效果图可以观察出,cell 上默认显示文字多于 4 行时省略,点击时文字全部展现,cell 也同时适应文字的高度。

  1. label 行数可以用 numberOfLines 属性来控制,改变它就可以改变文字的高度。

  2. cell 的高度需要变化,但是如果根据文字收缩时算一下高度,展开时又给 cell 一个高度这样会很麻烦,因为这样要去精确计算出文字高度,上下间距。所以这里我想到的是利用 tableView 估算 cell 高度的机制,cell 内的文字用 label 的约束将 cell "撑满"。

  3. 用一个 model 对应一个 cell 来防止复用数据错乱,然后展开与收缩用 tableView 的刷新动画就好了。

   4. 实际实现过程中遇到一些小坑,重点在处理动画流畅思路上。

【代码实现】

  1. 开启 tableView 估算机制

- (HomeView *)homeView
{
if (!_homeView) {
_homeView = [[HomeView alloc] init];
_homeView.backgroundColor = [UIColor whiteColor];
_homeView.tableView.dataSource = self;
_homeView.tableView.delegate = self;
_homeView.tableView.estimatedRowHeight = ;
[_homeView.tableView registerClass:[HomeCell class] forCellReuseIdentifier:NSStringFromClass([HomeCell class])];
[self.view addSubview:_homeView];
}
return _homeView;
}

  2. label 默认 numberOfLines 设置

- (UILabel *)contentL
{
if (!_contentL) {
_contentL = [[UILabel alloc] init];
_contentL.frame = CGRectMake(, , self.contentView.bounds.size.width, );
_contentL.lineBreakMode = NSLineBreakByTruncatingTail;
_contentL.numberOfLines = ;
[self.contentView addSubview:_contentL];
}
return _contentL;
}

  3. cell 数据设置 (通过 model 内 isOpen 来防止 cell 复用数据发生错乱)

- (void)setModel:(HomeModel *)model
{
_model = model;
self.contentL.text = model.title; if (model.isOpen) {
self.contentL.numberOfLines = NSIntegerMax;
} else {
self.contentL.numberOfLines = ;
}
}

  4. 点击时 tableView 动画刷新

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
HomeCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.model.isOpen = !cell.model.isOpen; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

【细节优化】

  上面的实现看似美好且不费力,但实际多滑两下,多点一些不同高度的 cell,会发现它的展开动画明显不流畅,会出现一点抖动状况。如下:

  

  看到这里,展开和收缩动画在这个 cell 上简直抽风了,有种突然截断了的感觉。这是肯定不能忍的。

  优化分析:

  tableView 动画不会有问题,是很正常的刷新对应的 cell。唯一可能出问题的就是 cell 的估算机制。因为 cell 我们默认给的高度是 80,所以当 cell 实际高度与默认高度相差太大时,就会出现这种问题了。

  解决方案:  

  我们还是采用 cell 高度的估算机制,但要让系统尽可能估计得准确,减少它调整高度带来的动画不流畅。那就是利用 tableView 返回估算高度的代理方法,我们先给它算好一个高度,并且这个高度肯定基本准确。(注意: 提前在拿到 model 数据时就算好 cell 高度存放在 model 中,而不是在 tableView 代理方法中去计算 cell 高度,因为代理方法调用太频繁,那里做一些简单取值操作就好,不然当数据量大时影响 tableView 滑动性能。)

  1. 在 model 获取数据时就算好 cell 数据的高度。在 HomeModel 加一个 cellHeight 属性,并重写 setTitle: 方法。如下:

- (void)setTitle:(NSString *)title
{
_title = title; CGFloat w = [UIScreen mainScreen].bounds.size.width - ;
CGFloat h = MAXFLOAT;
NSDictionary *dict = @{NSFontAttributeName: [UIFont systemFontOfSize:]};
CGFloat height = [title boundingRectWithSize:CGSizeMake(w, h) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size.height;
_cellHeight = height + ;
}

  2. 在控制器中加上 tableView 返回估算高度的代理方法设置如下:

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
HomeModel *model = self.testDataArray[indexPath.row];
return model.cellHeight;
}

  这样再运行,无论怎么滑怎么点,都十分完美。

ios-tableViewcell展开与收缩动画处理的更多相关文章

  1. ios知识点总结——UITableView的展开与收缩及横向Table

    UITableVIew是iOS开发中使用最为广泛的一种控件,对于UITableView的基本用法本文不做探讨,本文主要是针对UITableView的展开与收缩进行阐述,在文章的后面也会探讨一下横向ta ...

  2. max-height实现任意高度元素的展开收缩动画

    http://dobinspark.com.cn/ 前言: 在说到实现元素的展开收缩,通常的想法是通过控制display的元素属性和none之间的切换,虽然说功能可以实现,但是这种展开是没有任何动画的 ...

  3. 右上角鼠标滑过展开收缩动画效果js代码的演示页面

    http://files.cnblogs.com/files/tanlingdangan/top_right.rar.gz 右上角鼠标滑过展开收缩动画效果js代码的演示页面http://www.51x ...

  4. 【iOS系列】-UITableViewCell的展开与收缩的实现思路

    UITableViewCell的展开与收缩的实现思路 现在项目中很多地方都会用到,所以我这里介绍一种可以复用的思路,这与文章后面的Swift的实现思路不同,具体大家可自行对比. Demo项目地址 开始 ...

  5. iOS学习笔记-自定义过渡动画

    代码地址如下:http://www.demodashi.com/demo/11678.html 这篇笔记翻译自raywenderlick网站的过渡动画的一篇文章,原文用的swift,由于考虑到swif ...

  6. iOS开发UI篇—核心动画(UIView封装动画)

    iOS开发UI篇—核心动画(UIView封装动画) 一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画 ...

  7. iOS开发UI篇—核心动画(转场动画和组动画)

    转自:http://www.cnblogs.com/wendingding/p/3801454.html iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的 ...

  8. iOS开发UI篇—核心动画(关键帧动画)

    转自:http://www.cnblogs.com/wendingding/p/3801330.html iOS开发UI篇—核心动画(关键帧动画) 一.简单介绍 是CApropertyAnimatio ...

  9. iOS开发UI篇—核心动画(基础动画)

    转自:http://www.cnblogs.com/wendingding/p/3801157.html 文顶顶 最怕你一生碌碌无为 还安慰自己平凡可贵 iOS开发UI篇—核心动画(基础动画) iOS ...

随机推荐

  1. oracle索引查询

    /*<br>* *查看目标表中已添加的索引 * */ --在数据库中查找表名 select * from user_tables where  table_name like 'table ...

  2. Spring的启动流程

    spring的启动是建筑在servlet容器之上的,所有web工程的初始位置就是web.xml,它配置了servlet的上下文(context)和监听器(Listener),下面就来看看web.xml ...

  3. (十四)Android NDK混淆

    1.ollvm下载编译 我的是macbook环境. 参考obfuscator官网:https://github.com/obfuscator-llvm/obfuscator/wiki 执行下面的命令下 ...

  4. GITHUB readme基本语法

    一.标题写法: 第一种方法: 1.在文本下面加上 等于号 = ,那么上方的文本就变成了大标题.等于号的个数无限制,但一定要大于0个哦.. 2.在文本下面加上 下划线 - ,那么上方的文本就变成了中标题 ...

  5. python面向对象:组合、封装、property装饰器、多态

    一.组合二.封装三.property装饰器四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 3. ...

  6. PAT Basic 1052 卖个萌 (20 分)

    萌萌哒表情符号通常由“手”.“眼”.“口”三个主要部分组成.简单起见,我们假设一个表情符号是按下列格式输出的: [左手]([左眼][口][右眼])[右手] 现给出可选用的符号集合,请你按用户的要求输出 ...

  7. Apache版本兼容性问题

    Apache 版本2.2.31 版本对于谷歌浏览器不兼容.IE8版本可以正常使用 当使用了Apache 高版本的话就解决了 出现以下现象

  8. Airtest 支持的手机,系统等环境

    据个人经验,Airtest 支持的以下设备会跑的比较666 Android 平台 华为荣耀9青春版 版本:8.0.0 型号:LLD-AL10 评价:自动化运行最6 华为 荣耀10青春版 版本:9.0. ...

  9. Python&Selenium 数据驱动【unittest+ddt】

    一.摘要 本博文将介绍Python和Selenium做自动化测试的时候,基于unittest框架,借助ddt实现数据驱动 二.测试代码 # encoding = utf-8 ""& ...

  10. 用cmd 如何输入命令,进入文件夹

    用cmd 如何输入命令 进入文件夹 盘符: 例如想进入D盘 d: cd 进入到当前盘某个目录.cd \ 进入当前盘根目录cd \windows 进入到当前盘Windows目录cd.. 退出到上一级目录 ...