ドラッグで「戻る」「閉じる」ができるDraggableNavigationControllerを作ってみた
DraggableNavigationContoller この仕組みはiOS 13に標準搭載されましたので、カスタマイズ不要となりました。
ViewControllerの画面遷移を思いのままにカスタマイズ
モーダルの場合はtransitioningDelegateメソッド
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return animationController
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactionController
}
タブバーやナビゲーションの遷移は自身のdelegateメソッド
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return animationController
}
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactionController
}
これを設定するとナビゲーションのエッジスワイプを自動的に無効にしてくれるみたい。
カスタマイズには2種類のクラスを使います
アニメーター(UIViewControllerAnimatedTransitioning)
どんな動きをするか、純粋にアニメーションだけを担当します。
コンテキストから画面遷移に必要な2画面分のVCとviewを取得できる。
戻る場合は前の画面が回転前のままかもしれないので正しいframeをセットしておく。
従来型のanimateだけでなく、animateKeyframesでキーフレームアニメにもできます。
ジェスチャーやインタラクターには関与しない。
これがなければ標準のアニメーションになります。
遷移処理はそれぞれ微妙に異なっていて、pushの逆再生でpopのように簡単にはいかないので多少手間がかかります。
インタラクター(UIPercentDrivenInteractiveTransition)
アニメーションを割合で制御します。
どんなアニメーションかは知らない。
ジェスチャーと仲が良い。
ドラッグ操作にはこれとアニメーターの両方が必要になる。
割合の基準幅は分割されているかもしれないのでスクリーンの幅は使わない。
Appleのサンプルでは、これの内部でジェスチャーをハンドリングさせてますが、VCを渡してやる必要があります。
ドラッグのジェスチャーコントロール
戻る(pop)
テーブルの水平方向のジェスチャーが効いている時は自動的にドラッグ無効
閉じる(dismiss)
ナビゲーションバーもジェスチャーが有効
スクロール中でもドラッグを追跡して一番上に戻ったらdismiss開始
まとめ
今回は少ない機能でしたが、高速操作や横スクロールへの対応、iPadで便利なプレゼンターなどまだまだ改善させる余地があります。業務の合間に人気ライブラリ作ってる方って大変でしょうね。