这篇文章主要讲解了“分析iOS自适应cell行高”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“分析iOS自适应cell行高”吧!
成都创新互联主要为客户提供服务项目涵盖了网页视觉设计、VI标志设计、网络营销推广、网站程序开发、HTML5响应式成都网站建设公司、手机网站开发、微商城、网站托管及网站建设维护、WEB系统开发、域名注册、国内外服务器租用、视频、平面设计、SEO优化排名。设计、前端、后端三个建站步骤的完善服务体系。一人跟踪测试的建站服务标准。已经为成都被动防护网行业客户提供了网站建设服务。
需求背景
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:
/**cell自动计算行高@param tableView tableView@param indexPath indexPath@param contentViewWidth cell内容宽度,不确定可传0@return cell高度*/+ (CGFloat)FSCellHeightForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)contentViewWidth bottomOffset:(CGFloat)bottomOffset;/**cell自动计算行高优化版@param tableView tableView@param indexPath indexPath@param cacheKey 当前cell唯一标识符@param contentViewWidth cell内容宽度,不确定可传0@return cell高度*/+ (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(本地下载)
感谢各位的阅读,以上就是“分析iOS自适应cell行高”的内容了,经过本文的学习后,相信大家对分析iOS自适应cell行高这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!
文章名称:分析iOS自适应cell行高
标题来源:http://lswzjz.com/article/pjhigi.html