您的位置:首页 > 产品设计 > UI/UE

非常规使用 UITableView, reloadSections时动画效果异常

2017-02-25 13:25 1161 查看
直接上现象:



可以看到在调用
reloadSections
方法更新
Section 2
时,由于
Section 1
只有一个
Header
区域,没有对应的
Cell
, 从而引起了这个现象。更新调用的方法如下:

func reloadSection2(_ sender: UIButton) {
tableView.reloadSections(IndexSet.init(integer: 2), with: .automatic)
}


问题说明

按照通常的逻辑关系,没有行数的
Section
压根就不应该创建相关的UI,但在实际应用时,由于数据获取和UI显示的不同步或者某些历史原因,导致我们先给UI占了位,等数据获取后再刷新显示,这就出现了上面所说的场景和现象了。

如果情况只是这样,那还好搞。但事实是,有时候你还在
Section
没有内容的时候把那个
Section Header
给隐藏起来了,这就给定位问题带来了很大的麻烦。我和我的小伙伴花了整整一天,才在项目中找到原因,简直累死。现在做了Demo来演示这个问题。

解决方案1 - 取消动画的方式

全局刷新
TableView
:

func reloadSection2(_ sender: UIButton) {
tableView.reloadData()
}


效果:



强制取消
reloadSections
的动画效果:

func reloadSection2(_ sender: UIButton) {
UIView.performWithoutAnimation {
tableView.reloadSections(IndexSet.init(integer: 2), with: .automatic)
}
}


效果:



可是如果我们非要保留这个过渡动画呢?

你没有看错,需求有时就是这个样子的,所以才会发生流血事件 -_-#

解决方案2 - 保留动画效果

给空Section指定一个行,并通过设置高度控制显示/隐藏

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return 1 //强制给Section 1指定一行Cell
}
return 3
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 {
return 0 //通过控制Section 1的Cell的高度来隐藏这个指定的Cell
}
return 40
}


效果:



如果你把动画放慢,会发现在动画过程中,
Section 1
强制指定的的Cell有时会在动画初期出现,这个是由于
View
clipsToBounds
没有设置的缘故,导致视图的内容可以在边界外显示出来。我们可以给
Cell
设置这个属性,以消除这个影响:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

cell.textLabel?.text = self.randomSmallCaseString(length: 20);
cell.backgroundColor = UIColor.green
cell.clipsToBounds = true; // 设置这个属性,那内容限制在视图的边框内部不会越界显示
return cell
}


Demo下载 - Raspberry Pi

Demo - CSDN附件

这种方法不官方,但确实可行,是目前我想到的保留动画的解决方式。如果你们有其它的解决方式,请一定通知我: <824219521@qq.com>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息