swiftの画面遷移で画面を上から下に表示する方法
はじめに
やりたかったことは画面上部のメニューバーに設定ボタンをおいてそれをタップすると、画面上からメニューが落ちてくるような動きでした。
単純に、presentViewControllerを呼び出す前にviewController.modalTransitionStyleに適当なスタイルを設定すればできるだろうくらいに軽く考えていたのですが、、、デフォルトで用意されている以外のアニメーションを設定する場合は自作しないといけないみたいでした
var viewController: MenuViewController = MenuViewController() viewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical // ★ここを適当な値にすればいけると思ってた self.presentViewController(viewController, animated: true, completion: nil)
実装方法
必要な作業としては、
・アニメーションの動きを記述するクラスの実装
・遷移元のViewControllerでUIViewControllerTransitioningDelegateプロトコルを実装
以下のコードだとanimationControllerForPresentedController、animationControllerForDismissedControllerの箇所です
ViewController.swift
class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
// カスタムアニメーション
var animationController = MenuAnimationController()
・・・
// メニューを表示します
func showMenu() {
var viewController: MenuViewController = MenuViewController()
viewController.transitioningDelegate = self
self.presentViewController(viewController, animated: true, completion: nil)
}
// ページを開くときに呼ばれます
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isClose = false
return animationController
}
// ページを閉じるときに呼ばれます
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isClose = true
return animationController
}
}MenuAnimationController.swift
class MenuAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
// 閉じる場合はtrueをセット
var isClose: Bool!
// アニメーションにかかる時間をセット
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 0.3
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 遷移元、遷移先ViewController
var toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
var fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
var containerView = transitionContext.containerView()
var screenBounds = UIScreen.mainScreen().bounds
// アニメーション終了時のframe
var finalFrame = transitionContext.finalFrameForViewController(toViewController)
// アニメーション開始時のframe(上からなのでマイナス値)
var menuStartFrame = CGRectOffset(finalFrame, 0, screenBounds.size.height * -1)
// メニューを開くアニメーション
if !isClose {
toViewController.view.frame = menuStartFrame
containerView.addSubview(toViewController.view)
UIView.animateWithDuration(
transitionDuration(transitionContext),
animations: {
toViewController.view.frame = finalFrame
},
completion: {
finished in
transitionContext.completeTransition(true)
}
)
// メニュー閉じるアニメーション
} else {
containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
UIView.animateWithDuration(
transitionDuration(transitionContext),
animations: {
fromViewController.view.frame = menuStartFrame
},
completion: {
finished in
transitionContext.completeTransition(true)
}
)
}
}
}
さいごに
やりかたとか全然しらなかったとはいえ実装するのに丸1日くらいかかりました、、、
うーん、難しい