Xcode
iOS
collectionView
tabbarController
swift4

TabBarItemを押下してViewのトップへ移動する機能の実装方法

よくInstagramやFacebookで実装されている、TabBarItemを押すとページの最上部までスクロールできる機能。

意外と実装方法に関する情報が少なく、特に日本語での記事が皆無に近かったので記録として残します。

実装

今回はCollection Viewを使用した時に参考になる例を扱います。同じくTable Viewでも少しいじるだけで実装できるはずです。

ViewController.swift
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITabBarControllerDelegate {

 @IBOutlet weak var collectionView: UICollectionView!

 var canScrollToTop: Bool = false

 override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.delegate = self
        collectionView.dataSource = self
 }

 override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        self.tabBarController?.delegate = self
        canScrollToTop = true
 }

 override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        canScrollToTop = false
 }

 // TabBarItemが押下された時に呼ばれる
 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {

        // 呼ばれたTabBarItemの番号(0, 1,..)
        let tabBarIndex = tabBarController.selectedIndex
        // 一応確認する
        print(tabBarIndex)

        if tabBarIndex == 0 && canScrollToTop {

            // 一番上に移動
            self.collectionView.setContentOffset(CGPoint.zero, animated: true)
        }
 }
}

ポイント

canScrollToTopの設置

一度目のdidSelectで受け取った押下アクションはTabを切り替える時に発動されるので、二度目のアクションでViewのトップへスクロールしたい。
そんな時に、canScrollToTopfunc viewWillAppeartruefunc viewWillDisappearfalseにすることで任意のTabBar上にいるときのみdidSelectを呼べます。

複数のタブ上でViewを動かしたいときのself.tabBarController?.delegate = selfの位置

self.tabBarController?.delegate = self

これをviewDidLoad()でなく、各ViewControllerのviewWillAppearの中で呼ぶことによって、VCごとの要素を使ったアクションを実装することが可能です。

終わりに

UITabBarControllerUITabBarControllerDelegateを使用してTabBarが押された時のアクションを追加する方法もいくつか見かけましたが、ViewControllerごとのCollection Viewだったりを使用したかったので今回の実装方法が一番しっくりきました。

他に良い方法があれば是非教えてください!

参考元

https://stackoverflow.com/questions/22392151/tap-tab-bar-to-scroll-to-top-of-uitableviewcontroller