【Xcode/Swift】XLPagerTabStripとCHIPageControlを使っておしゃれな遷移をさせてみる

ファイル構成

今回はたくさんファイルを追加します、この記事ではXibで開発していますがStoryboardでも同じ挙動になるのでご心配なく。

赤枠で囲ったファイルが今回作成するファイルです。

ライブラリのインストール

CHIPageControlがたくさんあるのは、シンプルにアニメーションの違いだけです。

とりあえず全部入れておきましょう。

pod 'XLPagerTabStrip', '~> 9.0'
pod 'CHIPageControl/Chimayo'
pod 'CHIPageControl/Fresno'
pod 'CHIPageControl/Jalapeno'
pod 'CHIPageControl/Jaloro'
pod 'CHIPageControl/Paprika'
pod 'CHIPageControl/Puya'
pod 'CHIPageControl/Aji'
pod 'CHIPageControl/Aleppo'

Storyboard (or Xib)

MainViewController

何も加えず、デフォルトの状態でOK

TabViewController

ScrollViewは以下のGIFを参考にContainerView接続を行っておきましょう。

CHIPageControlは以下を参考に設定してください、解説は下のテーブルをご確認ください。

解説
プロパティ名解説デフォルト値今回の設定
numberOfPages丸の数04
progressデフォルトでアクティブにする丸の位置(左から0番目)00
Padding丸同士の感覚512
Radius丸の大きさ106
inactiveTransparency非アクティブの丸の透明度(1が非透明、数字が下がるにつれて透明度は上がる)0.41
hidesForSinglePagenumberOfPagesが0の時にコントロールを非表示にするかどうかtrueDefault
borderWidth丸の線幅00

FirstViewController ~ ForthViewController

背景色何でもOK、Labelを一個真ん中に置くだけで良きです。

コーディング

全コピペでOKです。

import UIKit

extension UIViewController {
    func insertContainerViewController(_ viewController: UIViewController?, to targetView: UIView?, at index: Int) {
        guard let targetView = targetView else { return }
        guard let viewController = viewController else { return }
        guard !children.contains(viewController) else { return }
        viewController.view.frame = targetView.bounds
        addChild(viewController)
        targetView.insertSubview(viewController.view, at: index)
        viewController.didMove(toParent: self)
        targetView.layoutIfNeeded()
    }

}
import UIKit

final class MainViewController: UIViewController {

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

    func showTabViewController() {
        let controller = TabViewController()
        insertContainerViewController(controller, to: view, at: 0)
    }

}
import UIKit
import XLPagerTabStrip
import CHIPageControl

class TabViewController: PagerTabStripViewController, PagerTabStripDataSource, PagerTabStripIsProgressiveDelegate {

    @IBOutlet private weak var pageControl: CHIPageControlAleppo!

    private lazy var menuViewControllers: [UIViewController] = {
        // FirstView
        let firstViewController = FirstViewController()
        // SecondView
        let secondViewController = SecondViewController()
        // ThirdView
        let thirdViewController = ThirdViewController()
        // ForthView
        let forthViewController = ForthViewController()

        return [firstViewController, secondViewController, thirdViewController, forthViewController]
    }()

    override func viewDidLoad() {
        delegate = self
        datasource = self
        containerView.contentInsetAdjustmentBehavior = .never
        super.viewDidLoad()
        containerView.bounces = false
        containerView.alwaysBounceHorizontal = false
    }

    override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
        return menuViewControllers
    }

    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int) {}

    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool) {
        guard fromIndex != toIndex else {
            setNeedsStatusBarAppearanceUpdate()
            return
        }
        let isForward = (fromIndex < toIndex)
        pageControl.progress = Double(fromIndex) + ((isForward) ? Double(progressPercentage) : -Double(progressPercentage))
        guard indexWasChanged else { return }
        setNeedsStatusBarAppearanceUpdate()
        switch toIndex {
        case 0:
            print("DEBUG_PRINT: This is FirstView")
        case 1:
            print("DEBUG_PRINT: This is SecondView")
        case 2:
            print("DEBUG_PRINT: This is ThirdView")
        case 3:
            print("DEBUG_PRINT: This is ForthView")
        default:
            break
        }
    }

}
import UIKit
import XLPagerTabStrip

class <#何番目の#>ViewController: UIViewController {

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

}

extension <#何番目の#>ViewController: IndicatorInfoProvider {
    func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
        return IndicatorInfo(title: nil)
    }
}

これで正常に動作するはずです。