TabLayoutは、下の画像のようにTabを押したときにそれぞれ異なるページを表示するレイアウトです。上部にTabボタンが表示され、このボタンを押すと中央のページが変更されます。
TabLayoutとViewPager2を使用すると、Tabを押したときに他のページが表示する機能を簡単に実装できます。 ViewPager2 は Swipe でページをめくる UI を実装するために使用されるクラスで、既存にあった ViewPager の改善されたバージョンです。例を通して詳しく学びましょう。
この記事で紹介する例は、GitHub - TabLayoutExampleにアップロードしました。説明が不足している部分は完全なコードを参照してください。
1. 依存関係を追加
ViewPager2とTabLayoutを使用するために、gradleに次のように依存関係を追加します。
dependencies {
...
implementation 'com.google.android.material:material:1.4.0'
}
2. Layoutの設定
まず、メインプロジェクトを作成し、MainActivityのlayoutである activity_main.xml
を次のように変更します。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
- 簡単な説明のためにLinearLayoutに変わります
- TabLayoutとViewPager2を追加
3. Fragmentを追加
Tabを押したときに表示される画面はFragmentで実装されます。 3つのTabを追加するので、3つのFragmentを準備する必要があります。
Tab1Fragment.java
という名前で以下のように実装しました。
package com.example.myapplication
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.myapplication.databinding.Tab1FragmentBinding
class Tab1Fragment : Fragment() {
private lateinit var binding: Tab1FragmentBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = Tab1FragmentBinding.inflate(inflater, container, false)
return binding.root
}
}
layout ファイル tab_1_fragment.xml
は次のように実装します。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Tab1Fragment">
<ImageView
android:id="@+id/imageViewCat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/dog1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Tab2、Tab3のファイルも上記のようにしてください。
- View Bindingを使用してkotlinでlayoutで宣言されたオブジェクトにアクセスしました
- 各Fragmentは単に1つの画像を示しています
ちなみに、View Bindingを使用するには、App gradleで次のように設定する必要があります。
android {
buildFeatures {
viewBinding = true
}
4. ViewPager Adapterの実装
FragmentStateAdapterを継承するViewPager Adapterを次のように実装しました。 Adapterには、Tab全体の数と、どのTabを押したときにどのFragmentが生成されるべきかについての具体的な内容が実装されています。
package com.example.myapplication
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
private const val NUM_TABS = 3
class ViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {
override fun getItemCount(): Int {
return NUM_TABS
}
override fun createFragment(position: Int): Fragment {
when (position) {
0 -> return Tab1Fragment()
1 -> return Tab2Fragment()
2 -> return Tab3Fragment()
}
return Tab3Fragment()
}
}
5. TabLayoutの実装
MainActivityにはTabLayoutとViewPager2を連動させる実装があります。
package com.example.myapplication
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.databinding.ActivityMainBinding
import com.google.android.material.tabs.TabLayoutMediator
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val tabTitleArray = arrayOf(
"Tab1",
"Tab2",
"Tab3"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val viewPager = binding.viewPager
val tabLayout = binding.tabLayout
viewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitleArray[position]
}.attach()
}
}
- View Bindingを使用してTabLayoutとViewPager2オブジェクトにアクセスする
- ViewPagerに上記で作成したアダプタを設定します
- TabLayoutMediator は TabLayout と ViewPager2 を連動させるのに役立つオブジェクトです。上記のように引数で TabLayout と ViewPager2 オブジェクトを渡して
attach()
を呼び出すと連動になります。実装されたインタフェースは、Tabを押したときに選択されたTabのtitleを設定するコードです。
GitHub - TabLayoutExampleでサンプルプロジェクトを確認できます。画像ファイルや詳細コードを確認できます。
6. Scrollable
Tabが多いと、Tabのタイトルが見えにくくなることがあります。この場合、TabLayoutをScrollableに設定すると、次のように一部のTabが表示され、Tab位置からSwipeすると他のTabが表示されます。
Scrollableに設定するには、次のようにTabLayoutで tabMode
を scrollable
に設定するだけです。 (デフォルトは fixed
で、上記の例のようにTabが固定されています。)
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
7. TabにIconを追加
Icon を追加する方法は TabLayoutMediator を実装するとき、Tab の Icon 設定も一緒に実装してください。
private val tabTitleArray = arrayOf(
"Tab1",
"Tab2",
"Tab3"
)
private val tabIconArray = arrayOf(
R.drawable.ic_sunny,
R.drawable.ic_star,
R.drawable.ic_florist
)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitleArray[position]
tab.icon = getDrawable(tabIconArray[position])
}.attach()
8. 整理
ViewPager2でTabLayoutを実装する方法を簡単に調べました。サンプルプロジェクトはGitHub - TabLayoutExampleにアップロードしましたが、わからない部分がある場合はコードを確認してください。
Related Posts
- エラー解決:android gradle plugin requires java 11 to run. you are currently using java 1.8.
- Android - コルーチンとRetrofitによる非同期通信の例
- Android - コルーチンでURL画像を読み込む
- Android - 振動、Vibrator、VibrationEffectの例
- Some problems were found with the configuration of task
- Query method parameters should either be a type that can be converted into a database column or a List
- UbuntuでAndroid 12オープンソースをダウンロードしてビルド
- Android - ViewModelを生成する方法
- Android - Transformations.map(), switchMap() の違い
- Android-Transformations.distinctUntilChanged()소개
- Android - TabLayoutの実装方法(+ ViewPager2)
- Android - 携帯電話の電話番号を取得する方法
- Android 12 - Splash Screens
- Android 12 - インクリメンタルインストール
- Android - adbコマンドでbugreportログファイルの抽出
- Android - adbコマンドでAppデータを削除する
- Android - adbコマンドでアプリ無効化、有効化
- Android - adbコマンドで特定のパッケージのPIDを検索
- Android - adbコマンドでパーミッションGrantまたはRevoke
- Android - adbコマンドで特定のパッケージのプロセスの終了
- Android - adbコマンドでapkのインストール、削除、
- Android - adb push、pullでファイルのコピー、ダウンロード
- Android - adbコマンドでscreen capture保存
- Android - adbコマンドでSystemアプリの削除、インストール
- Android - adbコマンドでsettings value確認、変更、
- Android 12 - IntentFilterのexported明示的な宣言
- Android - adbコマンドで工場出荷時の(Factory reset)
- Android - adb logcatコマンドでログ出力
- Android - adbコマンドでメモリダンプ(dump-heap)
- Android - adbコマンドでApp強制終了(force-stop)
- Android - adbコマンドでServiceの実行、終了
- Android - adbコマンドでActivity実行
- Android - adbコマンドでBroadcast配信
- Android - PackageManagerにPackage情報を取得する
- Android - ACTION_BOOT_COMPLETEDイベント受信