Skip to content

Instantly share code, notes, and snippets.

@okmr-d
Created February 11, 2015 16:24
Show Gist options
  • Save okmr-d/f8141631ecb385425c32 to your computer and use it in GitHub Desktop.
Save okmr-d/f8141631ecb385425c32 to your computer and use it in GitHub Desktop.
Drawer Menu (iOS8〜)
//
// DOViewControllerWithSideBar.swift
// DOViewControllerWithSideBar
//
// Created by Daiki Okumura on 2015/02/11.
// Copyright (c) 2015 Daiki Okumura. All rights reserved.
//
import UIKit
class DOViewControllerWithSideBar: UIViewController, UIViewControllerTransitioningDelegate {
// MARK: UIViewControllerTransitioningDelegate
// このメソッドを実装することで、presentViewController:animated:completion:を実行するときの振る舞いに UIPresentationControllerの実装クラス(CustomPresentationController)が適用される。
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? {
let isRightBar:Bool = (presented.title == "RightBar")
println(isRightBar)
return DOSideBarPresentationController(presentedViewController: presented, presentingViewController: presenting, isRightBar: isRightBar)
}
// アニメーションは UIViewControllerAnimatedTransitioning の実装クラスを使うと書き換えることができる。
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let isRightBar:Bool = (presented.title == "RightBar")
println(isRightBar)
return DOAnimatedTransitioning(isRightBar: isRightBar, isPresent: true)
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let isRightBar:Bool = (dismissed.title == "RightBar")
println(isRightBar)
return DOAnimatedTransitioning(isRightBar: isRightBar, isPresent: false)
}
}
class DOSideBarPresentationController: UIPresentationController {
// 呼び出し元のViewControllerの上に重ねるオーバーレイView
var overlayView: UIView!
let isRightBar: Bool
let presentedViewFrame: CGRect
init(presentedViewController: UIViewController!, presentingViewController: UIViewController!, isRightBar: Bool) {
self.isRightBar = isRightBar
self.presentedViewFrame = presentedViewController.view.frame
super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)
}
// 表示トランジション開始前に呼ばれる
override func presentationTransitionWillBegin() {
// オーバーレイViewの設定
self.overlayView = UIView(frame: self.containerView.bounds)
self.overlayView.gestureRecognizers = [UITapGestureRecognizer(target: self, action: "overlayDidTouch:")]
self.overlayView.backgroundColor = UIColor.blackColor()
self.overlayView.alpha = 0.0
self.containerView.insertSubview(self.overlayView, atIndex: 0)
// トランジションを実行
self.presentedViewController.transitionCoordinator()?.animateAlongsideTransition({
[unowned self] context in
self.overlayView.alpha = 0.2
}, completion: nil)
}
// 非表示トランジション開始前に呼ばれる
override func dismissalTransitionWillBegin() {
// トランジションを実行
self.presentedViewController.transitionCoordinator()?.animateAlongsideTransition({
[unowned self] context in
self.overlayView.alpha = 0.0
}, completion: nil)
}
// 非表示トランジション終了後に呼ばれる
override func dismissalTransitionDidEnd(completed: Bool) {
if completed {
self.overlayView.removeFromSuperview()
}
}
// 子のコンテナのサイズを返す
override func sizeForChildContentContainer(container: UIContentContainer, withParentContainerSize parentSize: CGSize) -> CGSize {
return self.presentedViewFrame.size
}
// 呼び出し先のViewControllerのFrame(表示トランジション後)を返す
override func frameOfPresentedViewInContainerView() -> CGRect {
return self.presentedViewFrame
}
// レイアウト開始前に呼ばれる
override func containerViewWillLayoutSubviews() {
self.overlayView.frame = self.containerView.bounds
self.presentedView().frame = self.frameOfPresentedViewInContainerView()
}
// レイアウト開始後に呼ばれる
override func containerViewDidLayoutSubviews() {
}
// オーバーレイの View をタッチしたときに呼ばれる
func overlayDidTouch(sender: AnyObject) {
self.presentedViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
class DOAnimatedTransitioning: NSObject, UIViewControllerAnimatedTransitioning {
let isRightBar: Bool
let isPresent: Bool
init(isRightBar: Bool, isPresent: Bool) {
self.isRightBar = isRightBar
self.isPresent = isPresent
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 0.4
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
if isPresent {
presentAnimateTransition(transitionContext)
} else {
dissmissAnimateTransition(transitionContext)
}
}
// MARK: Custom
func presentAnimateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 呼び出し元ViewController
let presentingController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
// 呼び出し先ViewController
let presentedController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
// コンテナView 呼び出し先ViewControllerを指定した呼び出し元ViewControllerの背後に追加します。
let containerView: UIView! = transitionContext.containerView()
containerView.insertSubview(presentedController.view, belowSubview: presentingController.view)
// アニメーション
UIView.animateWithDuration(
self.transitionDuration(transitionContext),
animations: {
presentedController.view.frame.origin.x = self.isRightBar ? -presentedController.view.frame.width : presentedController.view.frame.width
},
completion: {
finished in
transitionContext.completeTransition(true)
})
}
func dissmissAnimateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 呼び出し先ViewController
let presentedController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
// コンテナView
let containerView: UIView! = transitionContext.containerView()
// アニメーション
UIView.animateWithDuration(
self.transitionDuration(transitionContext),
animations: {
presentedController.view.frame.origin.x = self.isRightBar ? containerView.bounds.size.width : -presentedController.view.frame.size.width
},
completion: {
finished in
transitionContext.completeTransition(true)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment