SlideMenuControllerSwiftの使い方とカスタマイズ


はじめに

こんにちは。
SlideMenuControllerSwiftというiOSライブラリの使い方などについて少し悩んだので共有してみたいと思います。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。

※画像のリンクはGitHubから引用させていただきました

https://github.com/dekatotoro/SlideMenuControllerSwift

導入について

実行環境は(Swift3.0.2)(Xcode8.2.1)で、CocoaPodsを利用し、サンプルを作成したいと思います。

Podfile.rb
use_frameworks!

pod 'SlideMenuControllerSwift'

サンプルや構成の確認

今回のライブラリ本体であるSlideMenuController(ピンク色)は左右にメニューを出す仕組みのベースとなるUIViewControllerで、メニューとなるUIViewControllerや上に乗るUIViewControllerを設定していく感じで、SlideMenuControllerはメニューを出した時に少しだけ見える背景のようになります

Storyboardを利用する方法

クラスの準備

左右にメニューを出すベースとなるUIViewController(SlideMenuController)

SlideMenuControllerを継承したクラスを用意します。
サンプルではピンク色のものです

SlideViewController.swift
import UIKit
import SlideMenuControllerSwift

class SlideViewController: SlideMenuController {

    override func awakeFromNib() {
        let mainVC = storyboard?.instantiateViewController(withIdentifier: "Main")
        let leftVC = storyboard?.instantiateViewController(withIdentifier: "Left")
        //UIViewControllerにはNavigationBarは無いためUINavigationControllerを生成しています。
        let navigationController = UINavigationController(rootViewController: mainVC!)
        //ライブラリ特有のプロパティにセット
        mainViewController = navigationController
        leftViewController = leftVC
        super.awakeFromNib()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

SlideMenuControllerに乗せるメインとなるUIViewController

サンプルではNavigationBarが黄緑色のものです

MainViewController.swift
import UIKit
import SlideMenuControllerSwift

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //NavigationBarが半透明かどうか
        navigationController?.navigationBar.isTranslucent = false
        //NavigationBarの色を変更します
        navigationController?.navigationBar.barTintColor = UIColor(red: 129/255, green: 212/255, blue: 78/255, alpha: 1)
        //NavigationBarに乗っている部品の色を変更します
        navigationController?.navigationBar.tintColor = UIColor.white
        //バーの左側にボタンを配置します(ライブラリ特有)
        addLeftBarButtonWithImage(UIImage(named: "menu")!)
    }
}

SlideMenuControllerに乗せる左側のメニューとなるUIViewController

サンプルではオレンジ色のものです
UISwitchなどを乗せていますが、今回はダミーとなります。ごめんなさい

LeftViewController.swift
import UIKit

class LeftViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Storyboardの準備

  • UIViewController 3つ (ピンク色とオレンジ色と黄緑色)

を用意し、以下を設定しました。

StoryboardID CustomClass接続名
オレンジ色 Left LeftViewController
ピンク色 Slide SlideViewController
黄緑色 Main MainViewController

実行

今回のサンプルでは左側のメニューのみの実装でしたが、
両方または右側だけに設定することも可能です。

SlideMenuControllerをStoryboardで管理しない方法

SlideMenuControllerをコードで作成してしまえばStoryboardやSlideMenuControllerのサブクラスを作成しなくても実装できてしまいます。
後のプロパティでscaleなどを変更し、SlideMenuControllerが画面に表示される割合が
増えた際に背景画像などを設定したい場合やstoryboardでviewの背景色を視覚的に確認したい場合などは上記の方法でも良いかもしれません。

AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let mainVC = storyboard.instantiateViewController(withIdentifier: "Main")
    let leftVC = storyboard.instantiateViewController(withIdentifier: "Left")
    let navigationController = UINavigationController(rootViewController: mainVC)
    let slideMenuController = SlideMenuController(mainViewController: navigationController, leftMenuViewController: leftVC)
    self.window?.rootViewController = slideMenuController
    self.window?.makeKeyAndVisible()
    return true
}

カスタマイズについて

NavigationBarにボタンを追加する

以下のコードでNavigationBarButtonItemを作成することでアクションなどを設定しなくてもメニューが開くボタンを作成することができます。
コードを記述する位置はmainViewControllerとなっているクラスで書くことができます。
mainViewControllerがUINavigationControllerの管理下でないとNavigationBarを持つことができないので注意が必要です。

//ライブラリによってExtensionされたUIViewControllerのメソッド
//左側にボタンを作成
addLeftBarButtonWithImage(_ buttonImage: UIImage)
//右側にボタンを作成
addRightBarButtonWithImage(_ buttonImage: UIImage)

設定プロパティ

SlideMenuOptionsという構造体が持つstaticプロパティに値を入れることで様々な設定をすることができるみたいです。

コード 説明
leftViewWidth: CGFloat = 270.0 左メニューの横幅
rightViewWidth CGFloat = 270.0 右メニューの横幅
leftBezelWidth: CGFloat? = 16.0 画面スワイプ時に感知する左からの横幅
rightBezelWidth: CGFloat? = 16.0 画面スワイプ時に感知する右からの横幅
rightPanFromBezel: Bool = true falseにするとスワイプでメニューを開くことができなくなる※1
contentViewScale: CGFloat = 0.96 メニューを開いた時のmainVCの縮み率
opacityViewBackgroundColor: UIColor = UIColor.black メニューを開いた時のmainVCにかかる色
contentViewOpacity: CGFloat = 0.5 メニューを開いた時のmainVCにかかる色のalpha値
contentViewDrag: Bool = false メニューを開いた時にmainVCがメニューのwidth分ずれて表示されるかどうか
shadowOpacity: CGFloat = 0 影の明るさ(0)
shadowRadius: CGFloat = 0 影のぼかし具合(0)
shadowOffset: CGSize = CGSize.zero 矩形からどれだけ影がずれているか※2
panFromBezel: Bool = true 画面スワイプでメニューを出せるかどうか
animationDuration: CGFloat = 0.4 メニューを出す速度
hideStatusBar: Bool = true ステータスバーを隠すかどうか
pointOfNoReturnWidth: CGFloat = 44.0 ※3
simultaneousGestureRecognizers: Bool = true 複数のジェスチャーに対応するかどうか※4
panGesturesEnabled: Bool = true スワイプでのメニュー開閉動作が可能かどうか
tapGesturesEnabled: Bool = true タップでのメニューを閉じる動作が可能かどうか

※1: RightにあってLeftにはない不可解なプロパティ?
※2: RightとLeft共に影をつけたい場合はどのように値を設定すれば良いのか分かりませんでした(><)
※3: ごめんなさい 値を変更しても変化を確認することができませんでした(><)
※4: mainVCなどに他のジェスチャーが含まれていた場合にも対応するかどうか?

関連:gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)

オプションを記述する位置

記述する位置はSlideMenuControllerを継承したクラス(ピンク色のVC)で、
super.viewDidLoad後でも設定ができたことを確認できましたが

please set them before calling the init method

とライブラリ説明にあったので、super.init前や生成前などに呼ぶ方が良いのかもしれません。

コードによるメニューの開閉

SlideMenuControllerのプロパティにUIViewControllerがセットされていない場合ではメニューを開くことはできません。

// 左側のメニューを開く、閉じる
openLeft()
closeLeft()
// 右側のメニューを開く、閉じる 
openRight()
closeRight()

参考にさせていただいた記事

見て頂いてありがとうございます