You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义转场后旋转设备,dismiss时originVC无法通过CGAffineTransform.identity恢复

解决自定义转场旋转后Dismiss视图无法铺满的问题

这个问题我之前做自定义转场动画时也碰到过,你添加destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)的解决方案是完全合理的,下面咱们来拆解一下原因和优化方向:

问题根源

当你present目标VC后,给原VC(originVC)设置了缩放的transform,此时设备旋转会触发这些问题:

  • 系统会尝试更新所有可见视图的frame以适配新方向,但originVC处于非活跃状态(被presented的VC覆盖),它的view transform会干扰系统的自动布局更新逻辑
  • 旋转完成后,originVC的view实际上保留了旋转前的frame尺寸,只是被transform缩放了;当你dismiss时把transform重置为identity,就会暴露这个尺寸不匹配的问题,导致视图无法铺满屏幕

为什么你的临时方案有效

transitionContext.finalFrame(for: destinationViewController)是UIKit提供的核心方法,它会根据当前设备方向、安全区域、界面层级等因素,返回目标视图控制器在转场完成后应该拥有的正确全屏frame。强制设置这个frame后,再结合transform = .identity,就能让originVC的view同时恢复正确的尺寸和无变换状态,自然铺满屏幕。

优化后的Dismiss动画代码

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    guard let originViewController = transitionContext.viewController(forKey: .from), 
          let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
    
    // 获取当前方向下的正确全屏frame
    let finalFrame = transitionContext.finalFrame(for: destinationViewController)
    let duration = transitionDuration(using: transitionContext)
    
    UIView.animate(withDuration: duration, animations: {
        originViewController.view.transform = CGAffineTransform(translationX: 0, y: finalFrame.height)
        // 先设置正确frame,再重置transform和cornerRadius
        destinationViewController.view.frame = finalFrame
        destinationViewController.view.transform = .identity
        destinationViewController.view.layer.cornerRadius = 0.0
    }, completion: { completed in
        transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    })
}

额外优化建议

  • 避免直接操作view的transform做缩放:如果业务允许,尝试用容器视图的Auto Layout约束来实现originVC的缩放效果,这样系统在旋转时能更准确地处理布局更新,减少冲突
  • 转场前刷新布局:在动画开始前调用destinationViewController.view.layoutIfNeeded(),确保所有布局都已更新到当前方向的状态
  • 监听旋转事件:如果需要更精细的控制,可以在originVC的viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)方法中,判断是否处于被presented状态,若处于则临时调整transform或frame,避免旋转后留下布局隐患

内容的提问来源于stack exchange,提问作者user7482031

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:26:05