我正在研究类似于 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 中看到这一点。
我尝试了以下方法,但它们都产生相同的结果:
最佳答案
问题是 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/