iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >关于iOS自适应cell行高的那些事儿
  • 504
分享到

关于iOS自适应cell行高的那些事儿

cell自适应行高 2022-05-31 04:05:13 504人浏览 泡泡鱼
摘要

前言 其实早就准备写这篇文章了,但是一直没有系统去整理一下相关的demo,加上最近离职了,各种事情忙的有点郁闷,所以一直拖沓了下来。回家休息了一段时间想起来写了一半的demo,在还

前言

其实早就准备写这篇文章了,但是一直没有系统去整理一下相关的demo,加上最近离职了,各种事情忙的有点郁闷,所以一直拖沓了下来。回家休息了一段时间想起来写了一半的demo,在还没找工作的这段空挡时间抽空完善了一下再写篇说明文档备忘一下。

需求背景

iOS的cell行高自适应是个非常常见的需求,也是一个非常简单的需求,之前我遇到过很多小伙伴不知道怎么来实现,在这里就一步步的来分析一下,供大家参考。

问题分析

其他的实现场景就不说了,我们现在来分析一下具体的需求,如图所示:

其实主要实现这几点就可以解决所谓的自适应行高的问题,下面我们就来逐步实现这个需求。

计算UITableViewCell的高度

说到计算高度,大家都不陌生,最简单常见的就是计算出每个子视图的高度累积起来返回我们所需要的cell高度,然后在UITableViewDelegate中调用:


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 666;
}

或者高度固定的情况下直接


self.tableView.rowHeight = 666;

但是这就要求我们需要提前拿到model中的数据来手动计算每个控件的高度,这样既麻烦又不能通用,所以在autolayout出来之后我们只要给cell的contentView的上下左右都添加了约束,系统就可以自动的帮我们实现高度的自适应,就是一定要保证cell的高度可以被子视图撑开就可以了,利用的是systemLayoutSizeFittingSize这个api

ioS8之后就更简单了,直接使用:


self.tableView.estimatedRowHeight = 666;
self.tableView.rowHeight = UITableViewAutomaticDimension;

就可以了,其中estimatedRowHeight是预估高度,这里要注意delegate中的返回高度方法就不用在写了。

关于这方面的文章,UITableView+FDTemplateLayoutCel的作者写的一篇文章十分详细,建议先去了解一下(优化UITableViewCell高度计算的那些事

但是这个方法实际上在有多个子视图的cell上滑动是很卡顿的,特别是在iOS8尤其是iOS10上卡顿尤为明显,这跟系统的算高机制有一定关系,具体可以看上面的文章,这里不再解释了。

如果脱离开autolayout来说,平时计算高度的话,最开始都是根据cell内子控件内容的高度来手动累加起来,但是这个方法每次都要去手动处理其中的算高逻辑,而且横竖屏切换的时候还要重新计算,在平时开发中就会浪费大量不必要的精力。所以后来我在项目中是通过调用layoutSubviews来获取到子控件的实际frame,这样就可以得到我们所需的cell高度值,如下代码所示:


cell.frame = CGRectSetWidth(cell.frame, contentViewWidth);
cell.contentView.frame = CGRectSetWidth(cell.contentView.frame, CGRectGetWidth(tableView.frame));
[cell layoutIfNeeded];

UIView *cellBottomView = nil;
if (cell.FS_cellBottomView) {
cellBottomView = cell.FS_cellBottomView;
}else if (cell.FS_cellBottomViews && cell.FS_cellBottomViews.count > 0) {
cellBottomView = cell.FS_cellBottomViews[0];
for (UIView *view in cell.FS_cellBottomViews) {
if (CGRectGetMaxY(view.frame) > CGRectGetMaxY(cellBottomView.frame)) {
cellBottomView = view;
}
}
}else {
NSArray *contentViewSubViews = cell.contentView.subviews;
if (contentViewSubViews.count == 0) {
cellBottomView = cell.contentView;
}else{
cellBottomView = contentViewSubViews[0];
for (UIView *view in contentViewSubViews) {
if (CGRectGetMaxY(view.frame) > CGRectGetMaxY(cellBottomView.frame)) {
cellBottomView = view;
}
}
}
}

CGFloat cellHeight = CGRectGetMaxY(cellBottomView.frame) + bottomOffset;

其中的cellBottomView是位于cell最底部的子视图,为了提高计算效率最好传入,如果不确定哪个子视图在最下面,可以传入一个视图数组contentViewSubViews,详细使用方式可以查看demo。

缓存cell高度

高度计算出来后,正常来说我们的需求已经达到了,但是如果这个高度值每次滑动的时候由于cell的复用机制都会重新计算,若果这个cell的自定义样式很复杂,子视图太多,那么大量的计算一定会损耗性能而导致明显的卡顿,所以缓存机制就是个必要的措施,更何况苹果也建议这样做; demo提供了两个计算行高的API:



+ (CGFloat)FSCellHeightForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)contentViewWidth bottomOffset:(CGFloat)bottomOffset;


+ (CGFloat)FSCellHeightForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath cacheKey:(NSString *)cacheKey cellContentViewWidth:(CGFloat)contentViewWidth bottomOffset:(CGFloat)bottomOffset;

第一种使用数组来做缓存,传入对应cell的indexPath作为数组索引值;第二种则采用字典来缓存数据,要求传入一个唯一标识符cacheKey来区分;

两种方式都可以准确获得cell高度,第一种实现更简洁,缺点就是数据源发生变化时,所有的缓存就会清空重新计算后缓存,比如reloadData的时候;第二种就是在前者的基础上添加一个区分不同cell的标识符,使用时还是建议使用第二种,不会清空缓存数据,轻量级页面没什么区别。总之两种方法都做了缓存数据的容错处理,支持以下方法:


@selector(reloadData),
@selector(insertSections:withRowAnimation:),
@selector(deleteSections:withRowAnimation:),
@selector(reloadSections:withRowAnimation:),
@selector(moveSection:toSection:),
@selector(insertRowsAtIndexPaths:withRowAnimation:),
@selector(deleteRowsAtIndexPaths:withRowAnimation:),
@selector(reloadRowsAtIndexPaths:withRowAnimation:),
@selector(moveRowAtIndexPath:toIndexPath:)

兼容横竖屏

这个需求实现较为简单,就是横屏和竖屏分别采用两套缓存数据,互不影响,切换横竖屏的时候自动切换数据源。


- (NSMutableArray *)indexCacheArrForCurrentOrientation
{
return UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) ? self.indexCacheArr_Portrait: self.indexCacheArr_Landscape;
}

最后实现的效果如图所示:

总之答题思路就是这些,使用方便,感兴趣的可以移步下载demo查看:FSAutoAdjust-cellHeightDemo (本地下载

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程网的支持。

--结束END--

本文标题: 关于iOS自适应cell行高的那些事儿

本文链接: https://www.lsjlt.com/news/30190.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 关于 sudo 的那些事儿
    觉得你已经了解了 sudo 的所有知识了吗?再想想。大家都知道 sudo,对吗?默认情况下,该工具已安装在大多数 Linux 系统上,并且可用于大多数 BSD 和商业 Unix 变体。不过,在与数百名 ...
    99+
    2023-06-05
  • 关于pt-archiver和自增主键的那些事
    目录前言分析解析结论本文Percona Blog 的译文,原文移步文章末尾的 阅读原文。 前言 pt-archiver 是一款常见的 表清理或者归档工具。 MySQL 中删除大表之前...
    99+
    2024-04-02
  • 详细聊聊关于Mysql联合查询的那些事儿
    目录联合查询之union 1. 查询中国各省的ID以及省份名称 2. 湖南省所有地级市ID、名字 3. 用union将他们合并 联合查询之union a...
    99+
    2024-04-02
  • 关于mybatis的一级缓存和二级缓存的那些事儿
    目录一、缓存是什么二、为什么需要缓存三、哪些数据会放到缓存四、mybatis一级缓存五、二级缓存六、注意事项一、缓存是什么 缓存其实就是存储在内存中的临时数据,这里的数据量会比较小,...
    99+
    2024-04-02
  • iOS自动化测试的那些干货:关于appium启动报错问题的解决办法
    我们在进行iOS Appium自动化测试的时候,会遇到环境配置、兼容使用问题,这里做个总结,以避免后续踩着这些坑。问题1. 提示no module “appium”解决:第1步,在终端输入命令cd /usr/local/binpip3 in...
    99+
    2023-06-04
  • 关于游戏行业租用高防服务器的注意事项有哪些
    游戏行业租用高防服务器的注意事项:1.服务器机房是否稳定。2.服务器的带宽跟线路是否符合公司的要求。3.了解公司的需要以及服务商擅长的防御类型。4.服务器的配置是否满足业务需求。具体内容如下:一、游戏服务器的稳定与机房有直接的关系。好的服务...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作