【问题标题】:Animating changes to presentingViewController during interactive dismissal在交互式解雇期间动画更改 presentingViewController
【发布时间】:2023-04-03 08:25:02
【问题描述】:

我正在开发类似于 Mail.app 的打开草稿行为的 UIPresentationController 子类。呈现视图控制器时,它不会一直到顶部,呈现的视图控制器会按比例缩小,就好像它正在回落一样。

它的基本要点如下:

class CustomPresentationController : UIPresentationController {

    // Create a 40pt space above the view.
    override func frameOfPresentedViewInContainerView() -> CGRect {
        let frame = super.frameOfPresentedViewInContainerView()
        let insets = UIEdgeInsets(top: 40, left: 0, bottom: 0, right: 0)
        return UIEdgeInsetsInsetRect(frame, insets)
    }

    // Scale down when expanded is true, otherwise identity.
    private func setScale(expanded expanded: Bool) {

        if expanded {
            let fromMeasurement = presentingViewController.view.bounds.width
            let fromScale = (fromMeasurement - 30) / fromMeasurement
            presentingViewController.view.transform = CGAffineTransformMakeScale(fromScale, fromScale)
        } else {
            presentingViewController.view.transform = CGAffineTransformIdentity
        }

    }

    // Scale down alongside the presentation.
    override func presentationTransitionWillBegin() {
        presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in
            self.setScale(expanded: true)
        }, completion: { context in
            self.setScale(expanded: !context.isCancelled())
        })
    }

    // Scale up alongside the dismissal.
    override func dismissalTransitionWillBegin() {
        presentingViewController.transitionCoordinator()?.animateAlongsideTransition({ context in
            self.setScale(expanded: false)
        }, completion: { context in
            self.setScale(expanded: context.isCancelled())
        })
    }

    // Fix the scaled view's frame on orientation change.
    override func containerViewWillLayoutSubviews() {
        super.containerViewWillLayoutSubviews()
        guard let bounds = containerView?.bounds else { return }
        presentingViewController.view.bounds = bounds
    }
}

这适用于非交互式演示或解雇。但是,在执行交互式解除时,presentingViewController.view 上的所有动画都以非交互方式运行。也就是说,缩放将在通常需要关闭的大约 300 毫秒内发生,而不是在 3% 关闭时保持在 3% 完成。

您可以在a sample project is available on GitHub.a video of the issue is on YouTube 中看到这一点。

我尝试了以下方法,但都产生了相同的结果:

  • 如上所示的并行动画。
  • 在 UIViewControllerAnimatedTransitioning 中制作动画。
  • 使用 CABasicAnimation 手动调整容器视图层的时间。

【问题讨论】:

    标签: ios custom-transition


    【解决方案1】:

    问题在于presentingViewController 不是演示文稿的containerView 的后代。 UIPercentDrivenInteractiveTransition 通过将containerView.layer.speed 设置为零并设置containerView.layer.timeOffset 来反映完成百分比。由于有问题的视图不是层次结构的一部分,因此它的速度保持在 1 并且正常完成。

    animateAlongsideTransition(_:,completion:) 的文档中明确说明了这一点:

    使用此方法可以执行不由动画对象本身处理的动画。 您指定的所有动画都必须出现在动画上下文的容器视图(或其后代之一)内。使用上下文对象的 containerView 属性来获取容器视图。 要在不从容器视图下降的视图中执行动画,请改用animateAlongsideTransitionInView:animation:completion: 方法。

    如文档所示,切换到animateAlongsideTransitionInView(_:,animation:,completion:) 可以解决问题:

    // Scale up alongside the dismissal.
    override func dismissalTransitionWillBegin() {
        presentingViewController.transitionCoordinator()?.animateAlongsideTransitionInView(presentingViewController.view, animation: { context in
            self.setScale(expanded: false)
        }, completion: { context in
            self.setScale(expanded: context.isCancelled())
        })
    }
    

    标题中对该方法的注释比文档更直接:

    // 如果视图不是容器视图的后代并且您需要此动画由 UIPercentDrivenInteractiveTransition 交互控制器驱动,则需要此替代 API。

    【讨论】:

      【解决方案2】:

      感谢您的回答,在 iOS 9.x 和 10.x 设备上遇到此问题 - 使用 animateAlongsideTransition(in:animation:completion:) 完成了工作。

      有趣的是,在 iOS 11.x 上 animate(alongsideTransition:completion:) 也适用于 presentingViewController (无需使用 animateAlongsideTransition(in: animation:completion:)) - 看起来 Apple 在最新的 iOS 中提升了一些东西。

      【讨论】:

        猜你喜欢
        • 2023-03-04
        • 1970-01-01
        • 2022-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-31
        • 1970-01-01
        • 2017-05-20
        相关资源
        最近更新 更多