缘起于看见书旗小说的列表有点击折叠的动效,觉得十分炫酷。想了三分钟,不知道怎么写。晚上百度了下,知道了大致流程,于是自己实现了下,发现不少坑,于是写下这篇博文

实现原理:

1 tableview cell高度自适应

2 点击cell时,控制cell对应的数据源显示,更新约束后,tableView reloadData

贴下核心代码:

class CellMdl:NSObject {
var title:String?
var img:UIImage?
var detail:String?
} class FoldCell:UITableViewCell { var title:UILabel!
var detail:UILabel!
var imgView:UIImageView!
var indicator:UIImageView! var mdl:CellMdl! override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addViews()
} required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
} func addViews() { } override func layoutSubviews() {
title.snp.makeConstraints { (make) in
make.top.left.equalTo(self)
make.height.equalTo(44)
make.right.equalTo(indicator.snp.left)
}
indicator.snp.makeConstraints { (make) in
make.centerY.equalTo(title)
make.right.equalTo(self)
}
imgView.snp.makeConstraints { (make) in
make.top.equalTo(title.snp.bottom)
make.left.right.equalTo(self)
}
detail.snp.makeConstraints { (make) in
make.top.equalTo(imgView.snp.bottom)
make.left.right.bottom.equalTo(self)
}
} func showIndicatorAni(back:Bool,blk:(()->Void)?) {
let rotate = !back ? CGAffineTransform(rotationAngle: .pi) : .identity
UIView.animate(withDuration: 0.3, animations: {
self.indicator.transform = rotate
}) { (finish) in
self.detail.text = !back ? self.mdl.detail : nil
self.imgView.image = !back ? self.mdl.img : nil
// self.layoutIfNeeded()
if blk != nil {
blk!()
}
}
} // 设置数据源
func setMdl(cellMdl:CellMdl) {
mdl = cellMdl
title.text = cellMdl.title
// detail.text = cellMdl.detail
// imgView.image = cellMdl.img
}
}

这里对应cell声明一个专属cell的model,为cell提供数据

实现autolayout的关键步骤是

  1.setModel时,仅将显示的头部视图赋值,未赋值视图应没内容自适应后不会显示,将传入的model用变量存下来(后续使用)

  2.点击动画,代码请细看showIndicatorAni函数

    这里有两参数,第一个back参数:是否折叠,第二个是个blk,方便外部进行操作。

    如果不折叠,即显示全部内容,将model的数据赋值给需要显示的视图;如果折叠,不需要显示全部内容,将不需显示的视图内容清空。

    动画完且数据设置完全后,更新约束self layoutIfNeed后将动作传出

然后是外部tableView点击的具体实现

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if previousCell != nil {
previousCell?.showIndicatorAni(back: true,blk: nil)
} if let foldcell = tableView.cellForRow(at: indexPath) as? FoldCell {
weak var weakSelf = self
foldcell.showIndicatorAni(back: false,blk: {
weakSelf?.tableView.reloadData()
})
previousCell = foldcell
}
}

这里设置个变量previousCell标识前一个选择的cell。为什么写这个变量?选择的cell动画后,前一个cell的动画要还原,并且显示的视图要隐藏,要隐藏,要隐藏!!!

然后新选择的cell.showIndicator,回调中刷新tableview

顺带提一下tableview设置的关键点

  1.cell自适应设置姿势

   tableView.estimatedHeight = 100

   tableView.rowHeight = UITableviewAutomaticDimension

  2.cell单选

   tableView.allowMutableSelection = false

效果图贴一张

最新文章

  1. mysql的DATE_FORMAT用法
  2. 百度地图坐标纠偏和转换工具和DLL
  3. 电话薄设计--java
  4. 0009《SQL必知必会》笔记05-表的创建与约束
  5. thinkphp 完整配置config.php
  6. BootSrap学习
  7. C++ 简易时间类
  8. mysql三
  9. codeforces 132C Logo Turtle(dp)
  10. 线程join
  11. 使用 Maven 部署 artifact 到 Nexus 教程
  12. OpenStack Block Storage安装配置use LVM
  13. abstract class与interface的区别与联系
  14. Spring Boot--war发布
  15. iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)
  16. C# -- 使用FileInfo获取文件信息
  17. C# 操作Session、Cookie,Url 编码解码工具类WebHelper
  18. Jenkins+docker自动部署
  19. 使用android-ndk官方ndkbuild例子
  20. js 功能

热门文章

  1. centos7网卡配置文件详解与固定服务器ip
  2. python 中 list 的append与extend区别
  3. Ubuntu 16.04搭建php5.6 Web服务器环境
  4. 微服务系列(二)GRPC的介绍与安装
  5. C 语言通用模板队列
  6. [leetcode] 35. 搜索插入位置(Java)(二分)
  7. 稀疏自编码器及TensorFlow实现
  8. GPU与显卡
  9. Yolov4性能分析(下)
  10. 如何为嵌入式应用选择适当的SSD