はじめに
Google MapやFaceBookアプリのように、右側にスワイプするとレフト画面が表示されるUIを作成します。
2画面を重ねて表示させてい場合はスワイプ専用のViewを作成し、
上下にメイン画面(MainCV)とレフト画面(LeftCV)が表示されるよう設定します。
その際に使われるのがContainer View Controllerです。
今回はContainerと操作に必要なパーツを乗せて、実装していきます。
手順
- Storyboardから必要なViewの配置
- ユーザーの操作設定
- Navigation Controllerの設定
- UIを制御するコードの記述
Storyboardから必要なViewの配置
- ContainerをObject Libraryから2つドラッグし、View Controllerへドロップする
- 同様にViewをView Controllerへドロップする
- わかりやすくするために名前を変更する
今回は名前を以下のように設定しました。
- Main CV → メイン画面を乗せるためのContainer View Controller
- Left CV → レフト画面を乗せるためのContainer View Controller
- Cover View → 画面を移動させたときに上の画面を覆うView
現在のエディタエリアは以下のようになっています。
わかりやすいようにViewに色をつけています。
このままではCover Viewが全体を覆っているため、後ろのUIが表示できません。
そこで
- Document OutlineからCover Viewを選択
- Editor EreaのAttribute InspectorからViewのBackgroundをClear Colorに設定
- User Interaction Enabledのチェックを外す
必要なViewの配置は以上です。
ユーザーの操作設定
次に、ユーザーの操作に反応させていきます。
タップやスワイプのイベントに反応するためにGesture Recognizerを配置していきます。
- Tap Gesture RecognizerをObject Libraryからドラッグし、Document OutlineのCover Viewへドロップする
- 同様にObject LibraryからSwipe Gesture Recoginizerを2個Viewへドロップする
- わかりやすくするために名前を変更する
Swipe Gesture Recoginizerは初期状態で右へ動くよう設定されています。
レフト画面からメイン画面に戻りたい場合、右側にあるメイン画面を左側にスライドさせたいので、
- Document OutlineのLeftSwipedを選択し、Attribute InspectorからSwipeをLeftに設定する
これで、Swipeの設定は以上です。
Navigation Controllerの設定
Container View ControllerとView Controllerの間にNavigation Controllerを設置します。
- Document OutlineからLeft VCを選択
- ツールバーからEditorを選択し、Embed In → Navigation Controllerをクリック
今回、レフト画面はメニューを表示させたいので、Table View Controllerに変更します。
- Object LibraryからTable View Controllerを適切な場所へドラッグ&ドロップ
- Navigation ControllerからTable View Controllerへセグエを繋げる
- 不必要になったグレー背景のView Controllerを削除
ユーザーの操作設定は以上です。
UIを制御するコードの記述
UI要素をコードへ接続していきます。
現在のView名をわかりやすくする
ソースコードを実装する前に、現在のView名をわかりやすくしましょう。
各Viewにクラスを指定
今回は3つのviewを使用しているので、3つクラスを用意します。
既にあるViewController.swiftはContainerVCの処理を記述したいので、新しくMainVC.swiftとLeftTV.swiftを作成します。
- Container VC → ViewController.swift(既存のものを使用)
- Main VC → MainVC.swift
- LeftTV → LeftTV.swift
作成したらインスペクタペインからそれぞれのクラスを対応させましょう。
View Controllerへ接続
まずはView ControllerにMainstoryboardのDocument Outlineから
- Main CV
- Left CV
- Cover View
を接続させます。
@IBOutlet weak var MainCV: UIView!
@IBOutlet weak var LeftCV: UIView!
@IBOutlet weak var CoverView: UIView!
次にスワイプした際に反応するよう、
- Tap Gesture Recognizer
- LeftSwpied
- RightSwpied
を記述します。
@IBAction func coverTapped(sender: AnyObject) {
}
@IBAction func leftSwiped(sender: AnyObject) {
}
@IBAction func rightSwiped(sender: AnyObject) {
}
スワイプした際に動く範囲やアニメーション方法を指定したいので、メソッドを指定します。
- showBackground() → LeftTV画面を表示させるために右に画面をズラすメソッド
- hideBackground() → MainVC画面を再表示させるために左に画面を戻すメソッド
@IBAction func coverTapped(sender: AnyObject) {
hideBackground()
}
@IBAction func leftSwiped(sender: AnyObject) {
hideBackground()
}
@IBAction func rightSwiped(sender: AnyObject) {
showBackground()
}
追加したプロパティで、LeftTV画面が見えているときに固定させます。
var isBackgroundVisible = false
func showBackground() {
if (self.isBackgroundVisible) { return }
self.isBackgroundVisible = true
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.MainCV.frame = CGRectOffset(self.CoverView.frame, 230, 0)
}, completion: nil)
self.CoverView.frame = CGRectOffset(self.CoverView.frame, 230, 0)
self.CoverView.userInteractionEnabled = true
}
func hideBackground() {
if (!self.isBackgroundVisible) { return }
self.isBackgroundVisible = false
UIView.animateWithDuration(0.3, animations: { () -> Void in self.MainCV.frame = CGRectOffset(self.CoverView.frame, -230, 0)}, completion: nil)
self.CoverView.frame = CGRectOffset(self.CoverView.frame, -230, 0)
self.CoverView.userInteractionEnabled = false
}
MainVCとLeftTVにも接続
最後にMainVCとLeftTVにもshowBackgroundMenu関数とhideBackgroundMenu関数を記述します。
func showBackgroundMenu() {
}
func hideBackgroundMenu() {
}
func showBackgroundMenu() {
}
func hideBackgroundMenu() {
}
ソースコード一覧
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var MainCV: UIView!
@IBOutlet weak var LeftCV: UIView!
@IBOutlet weak var CoverView: UIView!
@IBAction func coverTapped(sender: AnyObject) {
hideBackground()
}
@IBAction func leftSwiped(sender: AnyObject) {
hideBackground()
}
@IBAction func rightSwiped(sender: AnyObject) {
showBackground()
}
override func viewDidLoad() {
super.viewDidLoad()
let rightGesture = UISwipeGestureRecognizer(target: self, action: "rightSwiped:")
let leftGesture = UISwipeGestureRecognizer(target: self, action: "leftSwiped:")
let tapGesture = UITapGestureRecognizer(target: self, action: "coverTapped:")
leftGesture.direction = .Left
self.view.addGestureRecognizer(rightGesture)
self.view.addGestureRecognizer(leftGesture)
CoverView.addGestureRecognizer(tapGesture)
}
var isBackgroundVisible = false
func showBackground() {
if (self.isBackgroundVisible) { return }
self.isBackgroundVisible = true
UIView.animateWithDuration(0.3, animations: { () -> Void in
println(self.CoverView.frame)
self.MainCV.frame = CGRectOffset(self.CoverView.frame, 230, 0)
}, completion: nil)
self.CoverView.frame = CGRectOffset(self.CoverView.frame, 230, 0)
self.CoverView.userInteractionEnabled = true
}
func hideBackground() {
if (!self.isBackgroundVisible) { return }
self.isBackgroundVisible = false
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.MainCV.frame = CGRectOffset(self.CoverView.frame, -230, 0)
}, completion: nil)
self.CoverView.frame = CGRectOffset(self.CoverView.frame, -230, 0)
self.CoverView.userInteractionEnabled = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func todoListVCDidTapeditButton(VC: MainVC) {
self.showBackground()
}
func leftViewDidSelectCell(cellNumber: Int) {
self.hideBackground()
}
}
AutoLayoutでcoverViewがズレているとへんな動きになるので、AutoLayoutの指定を間違えないようにしてくださいね。
以上です。