iOSのTwitterのアプリのNavigationBarUIPageControlが入っていて素敵だなと思ってまねてみました。

ScreenShot92

完成した画面はこんな感じになります。

ScreenShot93

UIPageViewControllerを使って実装してみました。

簡単に実装方法を紹介します。

StoryBoard

こんな感じで実装してみました。

ScreenShot94

NavigationItemの上に一度UIViewをのせて、さらにその上にUILabelUIPageControlをのせています。

あとは@IBOutletViewController.swiftと接続してます。

ソースコード

わかりやすく一つのViewController.swiftにまとめてみました。

ViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import UIKit
class ViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
@IBOutlet weak var navigationTitle: UILabel!
@IBOutlet weak var navigationPageIndicator: UIPageControl!
var pageData = NSArray()
var _pageViewController: UIPageViewController? = nil
var pageViewController: UIPageViewController {
if _pageViewController == nil {
_pageViewController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
_pageViewController?.delegate = self
_pageViewController?.dataSource = self
}
return _pageViewController!
}
override func viewDidLoad() {
super.viewDidLoad()
let dateFormatter = NSDateFormatter()
self.pageData = dateFormatter.monthSymbols
self.navigationPageIndicator.numberOfPages = self.pageData.count
// Do any additional setup after loading the view, typically from a nib.
let startingViewController = self.viewControllerAtIndex(0, storyboard: self.storyboard!)!
self.currentPageIndicator(0)
let viewControllers: NSArray = [startingViewController]
self.pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: {(done: Bool) in
})
let pageViewRect = self.view.bounds
self.pageViewController.view.frame = pageViewRect
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Private methods
func viewControllerAtIndex(index: Int, storyboard: UIStoryboard) -> DataViewController? {
if self.pageData.count == 0 || (index >= self.pageData.count) {
return nil
}
let dataViewController: DataViewController = storyboard.instantiateViewControllerWithIdentifier("DataViewController") as DataViewController
dataViewController.dateObject = self.pageData[index]
return dataViewController
}
func indexOfViewController(viewController: DataViewController) -> Int {
if let dataObject: AnyObject = viewController.dateObject {
return self.pageData.indexOfObject(dataObject)
} else {
return NSNotFound
}
}
func currentPageIndicator(index: Int) {
self.navigationPageIndicator.currentPage = index
}
// MARK: - UIPageViewController delegate methods
func pageViewController(pageViewController: UIPageViewController, spineLocationForInterfaceOrientation orientation: UIInterfaceOrientation) -> UIPageViewControllerSpineLocation {
let currentViewController = self.pageViewController.viewControllers[0] as UIViewController
let viewControllers: NSArray = [currentViewController]
self.pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: {(done: Bool) in
})
self.pageViewController.doubleSided = false
return UIPageViewControllerSpineLocation.Min
}
// MARK: - UIPageViewController Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = self.indexOfViewController(viewController as DataViewController)
self.currentPageIndicator(index)
if (index == 0) || (index == NSNotFound) {
return nil
}
index--
return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var index = self.indexOfViewController(viewController as DataViewController)
if index == NSNotFound {
return nil
}
self.currentPageIndicator(index)
index++
if index == self.pageData.count {
return nil
}
return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)
}
}

UIPageViewControllerが表示するコントローラーは以下のようにしてます。

DataViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import UIKit
class DataViewController: UIViewController {
var dateObject: AnyObject?
@IBOutlet weak var textLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let obj: AnyObject = self.dateObject {
self.textLabel.text = obj.description
} else {
self.textLabel.text = "None"
}
}
}

簡単な解説

特に難しいことはしていません。

UIPageViewControllerDataSource

  • func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
  • func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?

のメソッドで現在地を把握してUIPageControlcurrentPageの値をセットしてます。

そこで値をセットするのが正しいかどうかはわかりませんが…。

終わりに

ちょっと思ったのが、Twitterのアプリの場合はUIPageControlのサークルの大きさが小さいんですよね。

なので、もしかしたらカスタマイズしたUIPageControlを使っていると思います。

以上になります。