Swift中使用AutoLayout约束实现ViewController转场动画的问题
解决AutoLayout下UIViewController转场动画的问题
你遇到的这个问题太常见了——当用AutoLayout管理视图布局时,直接修改frame会和AutoLayout的约束规则打架,要么动画跳变,要么布局直接乱掉。下面给你梳理下正确的实现思路和代码示例:
核心思路
在AutoLayout环境下做转场动画,操作视图约束才是正确姿势,而不是直接改frame。简单来说就是先给目标视图设置好动画起始状态的约束,触发布局让约束生效,再在动画闭包里修改约束值,通过刷新布局来驱动动画。
具体实现步骤&代码示例
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { // 1. 先拿到转场需要的核心对象 guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to), let toView = toVC.view else { transitionContext.completeTransition(false) return } let containerView = transitionContext.containerView // 2. 把目标视图加到容器里,设置初始约束(比如从屏幕右侧滑入的起始状态) containerView.addSubview(toView) toView.translatesAutoresizingMaskIntoConstraints = false // 初始时让目标视图的左边缘和容器右边缘对齐,也就是完全在屏幕外 let leadingConstraint = toView.leadingAnchor.constraint(equalTo: containerView.trailingAnchor) NSLayoutConstraint.activate([ leadingConstraint, toView.topAnchor.constraint(equalTo: containerView.topAnchor), toView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), toView.widthAnchor.constraint(equalTo: containerView.widthAnchor) ]) // 3. 强制刷新布局,让初始约束生效,不然动画会从默认位置开始 containerView.layoutIfNeeded() // 4. 执行动画:修改约束值,再刷新布局触发动画 UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { leadingConstraint.constant = 0 // 让目标视图滑入屏幕内 containerView.layoutIfNeeded() // 应用约束变化,驱动动画 }) { finished in // 5. 动画结束后一定要通知转场上下文,确保转场状态正确 transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } }
额外小贴士
- 如果是做dismiss动画(从第二个VC回到第一个VC),逻辑类似,只是改成修改
fromView的约束就行 - 要是需要结合透明度、缩放这类动画,可以直接在动画闭包里修改视图的
alpha、transform属性,这些属性不受AutoLayout约束影响,能和约束动画完美配合 - 绝对要避免在动画过程中同时改
frame和约束,两者二选一,优先用约束
内容的提问来源于stack exchange,提问作者Mellao
相关产品推荐
相关产品推荐

