UITableviewCell 自适应高度的一种实现方法

UITableviewCell 高度自适应, 我们最熟悉的就是QQ空间的说说动态和微信朋友圈了. 之前自己网上找的一些教程,要么就是用UILabel或者UITextView作为例子, 要么就是计算高度了. 可是正如我所提到的说说和微信朋友圈, 那一个Cell的内容都是不固定的, 好几条评论都是多出来的view, 教程不适用,决定自己弄.

预备内容: Cocoapods, SnapKit , autolayout

UITableView

一般来说,Cell的高度通过tableviewdelegate中如下的方法设置

func tableView(UITableView, heightForRowAt: IndexPath) -> CGFloat

如果要自适应高度,就不要实现这个方法了,否则Cell的高度就依照此方法返回的高度了

UITableViewViewController中的设置如下:

self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.autoresizesSubviews = false
self.tableView.register(MyCell.self, forCellReuseIdentifier: MyCell.reuseID)

重点:

  1. 高度自适应: tableView.rowHeight = UITableView.automaticDimension
  2. 取消改变子视图大小: self.tableView.autoresizesSubviews = false
  3. delegate不去实现 func tableView(UITableView, heightForRowAt: IndexPath) -> CGFloat

自定义Cell: StackView + SnapKit 纯代码版本

tableView里注册的Cell是自己定义的:

在一个UITableViewCell里,子视图都放在contentView里,初始化Cell时,尺寸未定,通过使用设定好约束Stackview可以实现动态调整大小:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style:style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(stackview)
stackview.snp.makeConstraints { (maker) in
maker.bottom.top.leading.trailing.equalToSuperview()
}
}

这样定义后,一个Cell如果是添加多条评论(subview),在初始化时stackView.addArrangedSubview()即可.

tableview.dataSource中这样实现方法:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.reuseID, for: indexPath) as! MyCell
cell.stackview.subviews.forEach{$0.removeFromSuperview()}
data[indexPath.row].comments.forEach{ _ in cell.stackview.addArrangedSubview(a.initComment(text: "testtest"))}
return cell
}
  1. 从复用池中取出cell
  2. 清空一下stackview,否则里面会有上次使用时残留的view
  3. 向stacview中添加subview (自己定义的一个生成view的方法)

生成评论View的代码如下:

func initComment(text:String) -> UIView {
let view = UIView(frame: .zero)
view.backgroundColor = .blue
let label = UILabel()
label.text = text
view.addSubview(label)

label.snp.makeConstraints { (maker) in
maker.center.equalToSuperview()
}
view.snp.makeConstraints { (maker) in
maker.size.equalTo(CGSize(width: UIScreen.main.bounds.width, height: 40))
}
return view
}

因为此view是放到stackview里面的,所以不必设置frame,需要明确的size自己添加好约束,其余的让stackview自适应就好

效果

截图

ViewController代码如下:

class ViewController: UIViewController {

var data = [ CellInfo(title: "第一条", comments: []),
CellInfo(title: "第二条", comments: ["评论1","评论2"]),
CellInfo(title: "第三条", comments: ["onew","asdf","asdfasdfasd"])
]

@IBOutlet weak var tableView: UITableView! {
didSet{
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.autoresizesSubviews = false
self.tableView.register(MyCell.self, forCellReuseIdentifier: MyCell.reuseID)
}
}

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

extension ViewController:UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
data[indexPath.row].comments.append("新添了一条评论")
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}

extension ViewController:UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.reuseID, for: indexPath) as! MyCell
let a = cell
a.stackview.subviews.forEach{$0.removeFromSuperview()}
data[indexPath.row].comments.forEach{ comment in a.stackview.addArrangedSubview(a.initComment(text: comment))}
return cell
}

}
0%