我正在研究类似于 Mail.app 的开放草稿行为的 UIPresentationController 子类。当一个 View Controller 被呈现时,它不会一直到顶部,呈现的 View Controller 会缩小,好像它正在回落。

它的基本要点如下:

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 手动调整容器 View 层的时间。
  • 最佳答案

    问题是 presentingViewController 不是演示文稿的 containerView 的后代。 UIPercentDrivenInteractiveTransition 的工作原理是将 containerView.layer.speed 设置为零并设置 containerView.layer.timeOffset 以反射(reflect)完成百分比。由于有问题的 View 不是层次结构的一部分,它的速度保持在 1 并且正常完成。

    这在 animateAlongsideTransition(_:,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())
        })
    }
    

    标题中对该方法的评论比文档更直接:

    关于ios - 在交互式关闭期间对presentingViewController 进行动画更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36775216/

    10-13 05:00