はじめに
久しぶりに、UIPageViewControllerを使う機会があったので、
整理しておきたいと思います。
ちなみに、UIPageViewControllerとは、
ページめくりや紙をめくるようなアニメーションができるViewControllerです。
Tips
アニメーションの種類
UIPageViewControllerTransitionStyle
定数 | 説明 |
---|---|
.Scroll | ページめくり |
.PageCurl | 紙めくり |
めくる方向
UIPageViewControllerNavigationOrientation
定数 | 説明 |
---|---|
.Horizontal | 横方向 |
.Vertical | 縦方向 |
ページを送る方向
(1) 順方向
・横方向の場合は、左にスワイプで移動
・縦方向の場合は、上にスワイプで移動
extension SDTPageViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
return goFowardPage(viewController)
}
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
return goBackPage(viewController)
}
private func goBackPage(viewController: UIViewController) -> UIViewController? {
var index = (viewController as! SDTPageInnerViewController).pageIndex
if index == 0 || index == NSNotFound {
return nil
}
index -= 1
return viewControllerAtIndex(index)
}
private func goFowardPage(viewController: UIViewController) -> UIViewController? {
var index = (viewController as! SDTPageInnerViewController).pageIndex
if index == NSNotFound {
return nil;
}
index += 1
if index == imageFiles.count {
return nil;
}
return self.viewControllerAtIndex(index)
}
private func viewControllerAtIndex(index:Int) -> SDTPageInnerViewController? {
if imageFiles.count == 0 || index >= imageFiles.count {
return nil
}
if let vc = UIStoryboard.getViewController("Main", identifier: "SDTPageInnerViewController") as? SDTPageInnerViewController {
vc.pageIndex = index
vc.filePath = imageFiles[index]
return vc
}
return nil
}
}
(2) 逆方向
・横方向の場合は、右にスワイプで移動
・縦方向の場合は、下にスワイプで移動
順方向にめくるパターンとgoFowardPageとgoBackPageを逆にするだけです
extension SDTPageViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
return goBackPage(viewController)
}
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
return goFowardPage(viewController)
}
}
指定ページへ移動する
スライダーと連動させたり、途中から読むなどに利用できます
func scrollToPage(pageIndex: Int) {
if let currentViewController = viewControllerAtIndex(pageIndex) {
if let pageViewController = pageViewController {
pageViewController.setViewControllers([currentViewController],
direction: .Forward, animated: false, completion: nil)
}
}
}
ページ番号の取得
独自のページコントローラーやページ番号の表示に利用できます
extension SDTPageViewController: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
if let vc = pageViewController.viewControllers?.first as? SDTPageInnerViewController {
//ページ番号を表示
print(vc.pageIndex)
}
}
}
オプション
おすすめは、ページ間に余白を指定できるオプションです。
該当ページを表示しているときは、余白が表示されませんが、
ページをめくるとページ間に余白ができます。
定数 | 説明 |
---|---|
UIPageViewControllerOptionInterPageSpacingKey | 余白を指定する |

pageViewController = UIPageViewController(transitionStyle: .Scroll,
navigationOrientation: .Horizontal,
options: [UIPageViewControllerOptionInterPageSpacingKey : 20])
参考ソースコード
いつも過去に作成したソースコードをコピペしているので、こちらにメモで残しておきます。
横スクロールで、順方向にページがめくれるサンプルです。
(ちなみに、StoryBoardは割愛します。ご了承ください。)
土台のViewController
import UIKit
class SDTPageViewController : UIViewController {
private var pageViewController:UIPageViewController!
private var imageFiles = ["image01.jpeg","image02.jpeg","image03.jpeg","image04.jpeg","image05.jpeg"]
private var pageIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() {
if let startingViewController = viewControllerAtIndex(0) {
pageViewController = UIPageViewController(transitionStyle: .Scroll,
navigationOrientation: .Horizontal,
options: [UIPageViewControllerOptionInterPageSpacingKey : 20])
if let pageViewController = pageViewController {
pageViewController.dataSource = self
pageViewController.delegate = self
pageViewController.setViewControllers([startingViewController],
direction: .Forward,
animated: false,
completion: {done in})
pageViewController.view.frame = self.view.frame
addChildViewController(pageViewController)
self.view.addSubview(pageViewController.view)
}
}
}
func scrollToPage(pageIndex: Int) {
if let currentViewController = viewControllerAtIndex(pageIndex) {
if let pageViewController = pageViewController {
pageViewController.setViewControllers([currentViewController],
direction: .Forward, animated: false, completion: nil)
}
}
}
}
extension SDTPageViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
return goFowardPage(viewController)
}
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
return goBackPage(viewController)
}
private func goBackPage(viewController: UIViewController) -> UIViewController? {
var index = (viewController as! SDTPageInnerViewController).pageIndex
if index == 0 || index == NSNotFound {
return nil
}
index -= 1
return viewControllerAtIndex(index)
}
private func goFowardPage(viewController: UIViewController) -> UIViewController? {
var index = (viewController as! SDTPageInnerViewController).pageIndex
if index == NSNotFound {
return nil;
}
index += 1
if index == imageFiles.count {
return nil;
}
return self.viewControllerAtIndex(index)
}
private func viewControllerAtIndex(index:Int) -> SDTPageInnerViewController? {
if imageFiles.count == 0 || index >= imageFiles.count {
return nil
}
if let vc = UIStoryboard.getViewController("Main", identifier: "SDTPageInnerViewController") as? SDTPageInnerViewController {
vc.pageIndex = index
vc.filePath = imageFiles[index]
return vc
}
return nil
}
}
extension SDTPageViewController: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
if let vc = pageViewController.viewControllers?.first as? SDTPageInnerViewController {
print(vc.pageIndex)
}
}
}
extension UIStoryboard {
static func getViewController<T: UIViewController>(storyboardName: String, identifier: String) -> T? {
return UIStoryboard(name: storyboardName, bundle: nil).instantiateViewControllerWithIdentifier(identifier) as? T
}
}
ページ毎のViewController
import UIKit
class SDTPageInnerViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
var pageIndex = 0
var filePath = ""
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() {
imageView.image = UIImage(named: filePath)
}
}
まとめ
UIPageViewControllerでよく使うTipsを纏めました。
次回は、ピンチやダブルタップで拡大・縮小する方法を纏めたいと思います。
以上です。