はじめに
XLPagerTabStripというSwift製のiOSライブラリを使った際に、TabBarController
と絡めた実装をしました。storyboard
での設定等で少し詰まったりもしましたので、備忘録として投稿します。
動作環境
【Xcode】Version 12.0.1
【Swift】Version 5.3
【CocoaPods】version 1.9.3
実装後の画面
実装手順
1. TabBarController
の用意
-
Main.storyboard
の元々あるViewController
を削除して、TabBarController
を追加します。付属のViewController
も消しておいてください。(storyboard
1つに対してViewController
1つとする理由です。)
-
MainTabBarController.swift
を作成し、Main.storyboard
のClass
に割り当ててください。
class MainTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// 各画面となるViewControllerを格納する変数を用意
var viewControllers = [UIViewController]()
// それぞれの画面の設定(tabの画像など)
let tab1VC = UIStoryboard(name: "Bookmarks", bundle: nil).instantiateInitialViewController()
tab1VC?.tabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 0)
viewControllers.append(tab1VC!)
let tab2VC = UIStoryboard(name: "Favorites", bundle: nil).instantiateInitialViewController()
tab2VC?.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
viewControllers.append(tab2VC!)
self.setViewControllers(viewControllers, animated: false)
}
}
2. 各画面となるViewController
の用意
- 上記の
tab1VC
をBookmarks.storyboard
、tab2VC
をFavorites.storyboard
として用意します。それぞれUINavigationController
を設定し、見分けがつくようにタイトルを付けます。
3. XLPagerTabStrip
を導入
- CocoaPodsを利用します。
- ターミナルを開いて
cd 対象ファイル
で移動します。 -
pod init
でpodfile
作成 -
podfile
に下記を追加し保存して、pod install
にて完了です。
pod 'XLPagerTabStrip'
4. 管理元クラスButtonBarPagerTabStripViewController
の用意
-
ViewController
たちを管理するButtonBarPagerTabStripViewController
を継承したクラスを用意します。今回はBookmarks
を管理元とします。BookmarksViewController.swift
を作成します。
import UIKit
import XLPagerTabStrip
// 継承元を書き換える ( UIViewController → ButtonBarPagerTabStripViewController )
class BookmarksViewController: ButtonBarPagerTabStripViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
//管理されるViewControllerを返す処理
let firstVC = UIStoryboard(name: "First", bundle: nil).instantiateViewController(withIdentifier: "First")
let secondVC = UIStoryboard(name: "Second", bundle: nil).instantiateViewController(withIdentifier: "Second")
let thirdVC = UIStoryboard(name: "Third", bundle: nil).instantiateViewController(withIdentifier: "Third")
let childViewControllers:[UIViewController] = [firstVC, secondVC, thirdVC]
return childViewControllers
}
}
1. ボタン部分になるCollection View
の設置
-
ボタン部分になる
Collection View
を配置し、下記画像のようにAutoLayout
を設定します。Cell
は消しておきましょう。 -
Collection View
のクラスをButtonBarView
と結びつけ、ModuleをXLPagerTabStrip
とします。
-
Collection View
を右クリックします。Referencing Outlets
のNew Referencing Outlet
をViewController
にドラッグし、ButtonBarView
を選択します。
2. 切り替え部分になるScrollView
の設置
- 切り替え部分になる
ScrollView
を配置し、下記画像のようにAutoLayout
を設定します。 - あいまいなレイアウトと警告がでるので
Content Layout Guides
のチェックを外しましょう。
-
ScrollView
を右クリックします。Referencing Outlets
のNew Referencing Outlet
をViewController
にドラッグし、containerView
を選択します。
-
正しく繋ぐことができると、
ScrollView
の表示がContainerView
に変わります。
5. 管理されるViewController
たちの用意
- スワイプやボタンを押されて遷移する
ViewController
になります。 -
IndicatorInfoProvider
プロトコルを実装したUIViewController
を下記3つそれぞれ用意します。
-
First.storyboard
、FirstViewController
を用意。(storyboard
の背景色は赤色
) -
Second.storyboard
、SecondViewController
を用意。(storyboard
の背景色は青色
) -
Third.storyboard
、ThirdViewController
を用意。(storyboard
の背景色は緑色
)
import UIKit
import XLPagerTabStrip
class FirstViewController: UIViewController {
//ここがボタンのタイトルに利用されます
var itemInfo: IndicatorInfo = "First"
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension FirstViewController: IndicatorInfoProvider {
func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
return itemInfo
}
}
6. buttonBarの見た目と振る舞いを追加
import UIKit
import XLPagerTabStrip
class BookmarksViewController: ButtonBarPagerTabStripViewController {
override func viewDidLoad() {
// 画面UIについての処理
setupUI()
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 強制的に再選択し、changeCurrentIndexProgressiveを動作させる( 0番目 → 1番目 → 0番目 )
moveToViewController(at: 1, animated: false)
moveToViewController(at: 0, animated: false)
}
func setupUI() {
// ButtonBar全体の背景色
settings.style.buttonBarBackgroundColor = UIColor.white
// ButtonBarItemの背景色
settings.style.buttonBarItemBackgroundColor = UIColor.white
// ButtonBarItemの文字色
settings.style.buttonBarItemTitleColor = UIColor.lightGray
// ButtonBarItemのフォントサイズ
settings.style.buttonBarItemFont = .boldSystemFont(ofSize: 14)
// 選択中のButtonBarインジケーターの色
settings.style.selectedBarBackgroundColor = UIColor.black
// 選択中のButtonBarインジケーターの太さ
settings.style.selectedBarHeight = 2.0
// ButtonBarの左端の余白
settings.style.buttonBarLeftContentInset = 8
// ButtonBarの右端の余白
settings.style.buttonBarRightContentInset = 8
// Button内の余白
settings.style.buttonBarItemLeftRightMargin = 32
// スワイプやButtonBarItemタップ等でページを切り替えた時の動作
changeCurrentIndexProgressive = { oldCell, newCell, progressPercentage, changeCurrentIndex, animated in
// 変更されたか、選択前後のCellをアンラップ
guard changeCurrentIndex, let oldCell = oldCell, let newCell = newCell else { return }
// 選択前のセルの状態を指定
oldCell.label.textColor = UIColor.lightGray
// 選択後のセルの状態を指定する
newCell.label.textColor = UIColor.black
}
}
override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
//管理されるViewControllerを返す処理
let firstVC = UIStoryboard(name: "First", bundle: nil).instantiateViewController(withIdentifier: "First")
let secondVC = UIStoryboard(name: "Second", bundle: nil).instantiateViewController(withIdentifier: "Second")
let thirdVC = UIStoryboard(name: "Third", bundle: nil).instantiateViewController(withIdentifier: "Third")
let childViewControllers:[UIViewController] = [firstVC, secondVC, thirdVC]
return childViewControllers
}
}