我正在开发类似于 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 层的时间。
Best Answer-推荐答案 strong>
问题在于 presentingViewController 不是演示文稿的 containerView 的后代。 UIPercentDrivenInteractiveTransition 通过将 containerView.layer.speed 设置为零并设置 containerView.layer.timeOffset 来反射(reflect)完成百分比。由于有问题的 View 不是层次结构的一部分,因此它的速度保持在 1 并且正常完成。
这在 animateAlongsideTransition(_:,completion 的文档中有明确说明:
Use this method to perform animations that are not handled by the animator objects themselves. All of the animations you specify must occur inside the animation context’s container view (or one of its descendants). Use the containerView property of the context object to get the container view. To perform animations in a view that does not descend from the container view, use the animateAlongsideTransitionInView:animation:completion: method instead.
如文档所示,切换到 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())
})
}
标题中对该方法的注释比文档更直接:
// This alternative API is needed if the view is not a descendent of the container view AND you require this animation to be driven by a UIPercentDrivenInteractiveTransition interaction controller.
关于ios - 在交互式解雇期间动画更改 presentingViewController,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/36775216/
|