見出し画像

iOSエンジニアがAndroidアプリをリリースするまで3 〜BottomNavigationViewのFragmentをViewPager2で切り替える〜

前の記事で、BottomNavigationで切り替えるFragmentは毎回生成されていて無駄じゃない?と書きました。

ViewPagerでFragmentを切り替えることで毎回生成しなくて済むということで、実装しました。

ViewPager?ViewPager2?

私がAndroidの勉強をするのに使ったのは以下の入門書。

この本でもFragmentの切り替えにViewPagerを使っている箇所があり、参考にしました。

Android StudioでUIを選んでるとViewPager2があります。ViewPager2が。

スクリーンショット 2020-08-18 21.44.25

2って!

公式ドキュメントによると、

ViewPager2 は、ViewPager ライブラリの機能を拡張した改良版であり、ViewPager を使用していたときによく見られた問題点が解決されています。

とのこと。

まぁ、これから新しく実装する分にはViewPager2で良いでしょう。
それにしても2って。
もうちょっとなんかなかったんですかね。

タブ切り替えのたびにFragmentが生成される

前回の記事でも書いた通り、BottomNavigationはタブ選択のたびにFragmentが生成されます。
画面表示時(Fragment生成時)にAPIでバックエンドからデータを取得して、画面にリスト表示する。
なんてパターンはよくあると思います(今回開発しているアプリではAPIを叩いたりしませんが)。

そんな場合、毎回毎回APIをコールして、レスポンスが返ってくるまでぐるぐるインディケータ出して。。。
なんてやってるととにかく使い勝手が悪いし、無駄な通信が発生する。

一度Fragmentを生成したら、タブを切り替えても保持したままにして欲しい。

そこでViewPager2を使います。

ViewPager2でFragmentを切り替える

使い方は簡単。
1. ActivityのレイアウトにViewPager2をセット
2.FragmentStateAdapterのを継承したクラスを作成する
3.上記2で作成したクラスでは要素数(タブの数)、各インデックスに対応するFragmentを返すメソッドを定義
4.ActivityのViewPage2のadapterに2で作成したクラスをセット
5.タブが選択されたら、選択されたタブのインデックスを2で作成したクラスのcurrentItemにセット

FragmentStateAdapterを継承したクラス


class BottomNavigationPagerAdapter(fm: FragmentActivity) : FragmentStateAdapter(fm) {
   override fun getItemCount(): Int {
       return 3
   }

   override fun createFragment(position: Int): Fragment {
       when(position) {
           0 -> return HomeFragment()
           1 -> return DashboardFragment()
           else -> return NotificationsFragment()
       }
   }
}

Activityの実装

class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       bottomNavigationViewPager.adapter = BottomNavigationPagerAdapter(this)
       bottomNavigationViewPager.isUserInputEnabled = false
       
       nav_view.setOnNavigationItemSelectedListener {
           val currentItem =
               when(it.itemId) {
                   R.id.navigation_home -> 0
                   R.id.navigation_dashboard -> 1
                   else -> 2
               }
           bottomNavigationViewPager.setCurrentItem(currentItem, false)
           return@setOnNavigationItemSelectedListener true
       }
   }
}

ViewPagerと違って、ViewPager2では、スワイプを無効化するためにサブクラスを作らなくて済む。
bottomNavigationViewPager.isUserInputEnabled = false
ここでスワイプを無効化しています。

意外と簡単!

参考ページ

AndroidのViewPagerを下タブで切り替え
AndroidアプリへのBottom Navigationの導入
ViewPager2でスワイプを無効にする方法

前の記事
iOSエンジニアがAndroidアプリをリリースするまで2 〜BottomNavigationActivity 謎の隙間との格闘〜

この記事が気に入ったらサポートをしてみませんか?