我正在研究类似于 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% 完成。
您可以在 GitHub 上的示例项目中看到这一点。并且该问题的视频在 YouTube 上。
我尝试了以下方法,但它们都产生相同的结果:
- 如上所示的并行动画。
- UIViewControllerAnimatedTransitioning 中的动画。
- 使用 CABasicAnimation 手动调整容器视图层的时间。