UITableView更新时阴影消失重现问题的解决方法咨询
问题描述
我使用tableView.beginUpdates()和tableView.endUpdates()实现带有阴影的单元格展开/收缩功能,但表格更新时所有单元格的阴影会先消失,之后再重新出现。我尝试过在willDisplayCell中设置阴影,也试过将阴影添加到独立视图、contentView以及cell本身,均无效。请问如何保持阴影不消失?
附带相关代码:
extension UIView { func addTutShadow(shadowOpacity: Float? = nil) { self.layer.shadowColor = UIColor.black.cgColor self.layer.shadowOffset = CGSize(width: 0, height: 3) self.layer.shadowRadius = 12 * kHeightFactor self.layer.shadowOpacity = shadowOpacity ?? 0.12 } }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TopicListCard cell.topic = rankedTopics[indexPath.section] cell.backgroundColor = .clear cell.backgroundView = UIView() cell.selectedBackgroundView = UIView() cell.delegate = self cell.addTutShadow() cell.setup() return cell } var selectedIndex = -1 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if selectedIndex != indexPath.section { selectedIndex = indexPath.section tableView.beginUpdates() tableView.endUpdates() } else { selectedIndex = -1 tableView.deselectRow(at: indexPath, animated: true) tableView.beginUpdates() tableView.endUpdates() } }
解决方案
1. 避免重复添加阴影
单元格复用过程中,每次调用addTutShadow会重复设置阴影属性,加上表格更新时的重绘逻辑,容易引发阴影闪烁。可以给自定义cell添加标记,确保阴影仅被添加一次:
class TopicListCard: UITableViewCell { private var hasAddedShadow = false override func layoutSubviews() { super.layoutSubviews() guard !hasAddedShadow else { return } addTutShadow() hasAddedShadow = true } }
2. 启用图层光栅化优化
给添加阴影的视图开启光栅化,减少重绘时的阴影消失问题,同时保证清晰度:
extension UIView { func addTutShadow(shadowOpacity: Float? = nil) { self.layer.shadowColor = UIColor.black.cgColor self.layer.shadowOffset = CGSize(width: 0, height: 3) self.layer.shadowRadius = 12 * kHeightFactor self.layer.shadowOpacity = shadowOpacity ?? 0.12 // 开启光栅化并设置屏幕适配的缩放比例 self.layer.shouldRasterize = true self.layer.rasterizationScale = UIScreen.main.scale } }
3. 给内容容器视图添加阴影
不要直接给cell或contentView设置阴影,而是在contentView内部创建一个专门的容器视图,将cell的所有内容放入其中,再给这个容器添加阴影:
class TopicListCard: UITableViewCell { private let shadowContainer = UIView() func setup() { // 将容器视图添加到contentView并设置约束 contentView.addSubview(shadowContainer) shadowContainer.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ shadowContainer.topAnchor.constraint(equalTo: contentView.topAnchor), shadowContainer.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), shadowContainer.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), shadowContainer.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) ]) // 将原cell的内容视图全部添加到shadowContainer中 // ... 此处添加你的内容视图布局代码 // 设置容器背景色并添加阴影 shadowContainer.backgroundColor = .white shadowContainer.addTutShadow() } }
4. 优化表格更新逻辑
确保tableView(_:heightForRowAt:)方法能准确返回单元格展开/收缩后的高度,避免动画过程中cell布局出现异常。同时移除cellForRowAt中重复设置背景的冗余代码,减少不必要的重绘触发。
内容的提问来源于stack exchange,提问作者Michael Montalbano
相关产品推荐
相关产品推荐

