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
が非インタラクティブに実行されます。つまり、スケーリングは、3% が却下されたときに 3% の完了を維持するのではなく、通常は却下するのにかかる約 300 ミリ秒で発生します。
これは、GitHub で入手できるサンプル プロジェクトで確認できます。この問題のビデオは YouTube にあります。
次のアプローチを試しましたが、すべて同じ結果が得られます。
- 上記の並列アニメーション。
- UIViewControllerAnimatedTransitioning でのアニメーション化。
- CABasicAnimation を使用して、コンテナー ビューのレイヤーのタイミングを手動で調整します。