Swift UIView.animate在自定义UITableViewCell中无动画效果问题

问题复现场景
- 交互逻辑:点击蓝色
UIButton,移动橙色视图到对应按钮位置 - 按钮点击事件绑定代码:
for button in toggleButtons { button.addTarget(self, action: #selector(toggleButtonAction), for: .touchUpInside) }
- 共创建3个按钮,位置移动逻辑可正常执行,但动画过渡效果失效
- 原动画实现代码:
@objc func toggleButtonAction(_ sender: UIButton) { self.toggleLeading.constant = sender.frame.width * CGFloat(sender.tag) UIView.animate(withDuration: 3, delay: 0, options: .curveEaseIn, animations: { self.layoutIfNeeded() }, completion: nil) }
- 异常特征:相同代码在普通
UIViewController中运行动画完全正常,迁移到自定义UITableViewCell后,点击按钮橙色视图直接瞬移到目标位置,无平滑过渡。
根本原因
UITableViewCell的布局逻辑和普通UIViewController存在差异:
- 所有子视图、约束必须依托cell的
contentView生效,直接添加到cell本身的视图不会被系统正常纳入动画布局管理 - 原代码动画块中调用
self.layoutIfNeeded()仅触发cell根视图的布局刷新,实际承载约束、完成位置更新的是contentView,调用对象错误 - UITableView存在自动布局刷新机制,修改约束后系统可能在动画块执行前就完成了布局更新,导致动画块执行时已经是最终位置状态,无过渡空间。
修复代码
@objc func toggleButtonAction(_ sender: UIButton) { // 先强制刷新当前布局,清空所有待处理的布局任务 self.contentView.layoutIfNeeded() // 更新目标约束 self.toggleLeading.constant = sender.frame.width * CGFloat(sender.tag) // 对contentView执行动画块,触发约束渐变更新 UIView.animate(withDuration: 3, delay: 0, options: .curveEaseIn, animations: { self.contentView.layoutIfNeeded() }, completion: nil) }
额外注意点
- 橙色视图、按钮、约束的绑定对象必须是
contentView,不要直接绑定到cell自身 - 如果cell重写了
layoutSubviews方法,不要在该方法内写强制刷新布局的逻辑,否则会打断动画流程 - 如果是iOS 15及以上系统,检查是否开启了cell的
contentView自动调整内容相关的多余属性,必要时可关闭self.contentView.autoresizingMask = []避免自动布局干扰。
内容的提问来源于stack exchange,提问作者KimJitae
相关产品推荐
相关产品推荐

