使用NSLayoutConstraint时遭遇UIView动画故障求助
NSLayoutConstraint动画故障修复(从Autoresizing Mask迁移后)
问题场景
- 原布局:视图锚定父视图右上角,内部子视图采用Autoresizing Mask布局,运行无异常
- 迁移到NSLayoutConstraint后,修改视图宽高约束的动画出现位置跳动故障,表现为视图在动画过程中偏离右上角位置
布局示意图:
故障演示:
原动画代码:
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) { self.constraints.first(where: {$0.firstAttribute == .height})?.constant = dstSize.height self.constraints.first(where: {$0.firstAttribute == .width})?.constant = dstSize.width self.setNeedsLayout() self.layoutIfNeeded() }
修复方案
1. 调整约束修改时机
约束常量的修改必须放在动画闭包外部,动画闭包内仅执行布局更新操作。系统需要先捕捉到约束的变化,才能基于新旧约束值生成平滑过渡动画。
2. 确认锚点约束正确性
确保视图的锚定约束与原Autoresizing Mask行为一致:
- 绑定
trailing(右侧)约束到父视图的trailingAnchor - 绑定
top(顶部)约束到父视图的topAnchor
避免错误绑定left或bottom约束,否则动画时会出现位置偏移。
3. 禁用Autoresizing Mask自动转换
迁移时务必设置:
self.translatesAutoresizingMaskIntoConstraints = false
防止系统自动生成与自定义约束冲突的Autoresizing Mask转换约束,导致布局异常。
修正后的代码
// 先在动画闭包外更新约束常量 if let heightConstraint = self.constraints.first(where: {$0.firstAttribute == .height}) { heightConstraint.constant = dstSize.height } if let widthConstraint = self.constraints.first(where: {$0.firstAttribute == .width}) { widthConstraint.constant = dstSize.width } // 执行动画,仅在闭包内触发布局更新 UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) { self.layoutIfNeeded() }
内容的提问来源于stack exchange,提问作者Gralex
相关产品推荐
相关产品推荐

