みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
KotlinでAndroidアプリ画面にタブを実装する方法を、
実際のコードを用いてわかりやすく解説していきます!
この記事を読んでわかること…
・TabLayoutとViewPager2の使い方について
・タブ画面の実装手順
環境
- Kotlin (ver 1.9.0)
- Android Studio (Giraffe | 2022.3.1 Patch 3)
TabLayoutとViewPager2とは?
TabLayout
TabLayoutは、画面上部に「タブ(カテゴリーや項目の切り替えを行う部分)」を表示するためのUIコンポーネントです。タブをクリックすると、対応するコンテンツが切り替わります。
ViewPager2
ViewPager2は、画面をスワイプしてコンテンツを切り替える仕組みを提供するコンポーネントです。
タブと連携させることで、横スワイプによる切り替えが可能になります。
横スワイプ可能なタブの概要と仕組み
TabLayout
とViewPager2
を組み合わせると、以下のような操作が可能になります▼
- タブをタップして画面を切り替える
→TabLayout
がタブの操作を管理します。 - 横スワイプで画面を切り替える
→ViewPager2
がスワイプの操作を管理します。
この連携は、TabLayoutMediator
(タブとスワイプの動作をつなぐクラス)によって実現します。
TabLayoutとViewPager2を使ったタブ画面の実装手順
1. 必要な準備
プロジェクトのbuild.gradle
に以下の依存関係を追加します。
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
1行目:
「Googleの Designコンポーネント」を利用するためのライブラリです。TabLayout
を含む多くのコンポーネント(ボタン、ダイアログ、スナックバーなど)が利用可能になります
2行目:
ViewPager2を使用するためのライブラリです。
2. レイアウトの作成
以下のようなレイアウトを作成します。TabLayout
とViewPager2
を使った基本構造です。
res/layout/activity_main.xml
▼
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ポイント① TabLayout (タブ表示部分) -->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill" />
<!-- ポイント② ViewPager2 (スワイプで切り替える部分) -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
上記レイアウトは、以下の2つの主要なUIコンポーネントを含んでいます:
<!--ポイント① TabLayout (タブ表示部分)-->
TabLayout:
画面上部にタブ(ボタンのようなもの)を表示し、タブをタップすると対応する画面を表示します。
タブが水平に並びます。<!--ポイント② ViewPager2 (スワイプで切り替える部分)-->
ViewPager2:
画面のスワイプ操作を検知し、スワイプで画面(タブ)を切り替えます。TabLayout
と連携させることで、スワイプ操作でタブも切り替わるようになります。
これらをCoordinatorLayout
で囲って、レイアウトの動作を調整しています。
また、タブそれぞれの画面に対応するレイアウトファイルも用意してください。
res/layout/fragment_tab1.xml
▼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/textTab1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="タブ1の画面"
android:textSize="24sp"
android:textColor="#000000"
android:textStyle="bold" />
</LinearLayout>
res/layout/fragment_tab2.xml
▼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/textTab1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="タブ1の画面"
android:textSize="24sp"
android:textColor="#000000"
android:textStyle="bold" />
</LinearLayout>
3. Fragmentの作成
各タブで表示する内容をFragment
として作成します。
Tab1Fragment.kt ▼
class Tab1Fragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = inflater.inflate(R.layout.fragment_tab1, container, false)
return view
}
}
Tab2Fragment.kt ▼
class Tab2Fragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = inflater.inflate(R.layout.fragment_tab2, container, false)
return view
}
}
4. ViewPager2用のAdapter作成
ViewPager2
でタブの切り替えを管理するためのAdapter
を作成します。
class TabsPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = 2 // タブの数
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> Tab1Fragment()
1 -> Tab2Fragment()
else -> throw IllegalArgumentException("エラー")
}
}
}
このあと、上記TabsPagerAdapter
をViewPager2
にセットしますが
そうすることによってタブと画面の切り替えが連携します。
また、createFragment
メソッドでタブの位置に応じたFragmentを動的に作成します。
5. TabLayoutとViewPager2の連携
最後に、TabLayoutMediator
を使用して TabLayout
とViewPager2
を連携させます。
MainActivity.kt
▼
class MainActivity : AppCompatActivity() {
// ポイント①
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ポイント②
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// ポイント③
val adapter = TabsPagerAdapter(this)
binding.viewPager.adapter = adapter
// ポイント④
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = when (position) {
0 -> "Tab 1" // 最初のタブ
1 -> "Tab 2" // 2番目のタブ
else -> null
}
}.attach()
}
}
// ポイント①
ActivityMainBinding:
activity_main.xml に対応するバインディングクラス。
これにより、findViewById
を使わずにUIコンポーネント(例: tabLayout
, viewPager
)に直接アクセスできます。// ポイント②
binding = ActivityMainBinding.inflate(layoutInflater):
activity_main.xml のレイアウトをメモリに読み込み、対応するビューを操作可能にします。
setContentView(binding.root):
バインディングオブジェクトのルートビュー(binding.root
)を画面に表示します。// ポイント③
binding.viewPager.adapter = adapter:
ここで、ViewPager2にAdapterをセットします。// ポイント④
TabLayoutMediator:
スワイプで画面が切り替わったときに、対応するタブの選択状態が更新されます。
、タブに表示するテキストを設定します。
それでは、さっそくビルドしてみましょ〜!
タブが表示されて、横へスライドさせるとタブと画面が切り替わる画面が完成しました!
ここで注意!
View Bindingは、レイアウトファイル名から対応するバインディングクラスを自動生成します。
そのため、以下のルールに基づいて一致させる必要がありますのでご注意を!↓
レイアウトファイル名 → 自動生成されるバインディングクラス名:
レイアウトファイル名がactivity_main.xml
の場合 → ActivityMainBinding
というクラスが生成される
レイアウトファイル名がfragment_home.xml
の場合 → FragmentHomeBinding
というクラスが生成される
このように、View Bindingではファイル名 + Bindingという命名規則が厳密に適用されるため、ActivityMainBinding
を使用するには、レイアウトファイルがactivity_main.xml
でなければ動きません。
まとめ
おつかれさまでした!いかがでしたでしょうか!
タブを増やして、複数画面にスムーズにできるよう、
お好きにカスタマイズしてみてください!
技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
自分の市場価値をさらに向上させてみませんか?
それではまた次の記事でお会いしましょう!
コメント