【Kotlin/Android Studio】ViewPager2の使い方!スライドで画面遷移
この記事からわかること
- Android Studio/KotlinでViewPager2の使い方
- スライド(スワイプ)で画面を遷移させる方法
- コードでページを遷移するには?
- TabLayoutとの併用方法
- リスナーを追加してイベントを検知する
- RTLのサポート
- スライドを縦にする方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Android Studio:Flamingo
- Android:13
- Kotlin:1.8.20
画面をスライドさせてフラグメントを移動する方法
Androidアプリで画面をスライド(スワイプ)させることで滑らかに別の画面に遷移する機能を実装するにはViewPager2
を使用します。以前はViewPager
でしたが、改良されて今ではViewPager2
が活用されています。
実装方法
流れ
- レイアウトファイルにViewPager2を追加
- FragmentStateAdapterを定義
- アダプターの紐付け
レイアウトファイルにViewPager2を追加
レイアウトファイルにViewPager2
を設置します。この領域がスライドで画面が遷移していく領域になります。
<?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"
android:id="@+id/container"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentStateAdapterを定義
続いてFragmentStateAdapter
に準拠したAdapterクラスを用意します。中にはgetItemCount
メソッドとcreateFragment
メソッドをオーバーライドします。createFragment
メソッドの中ではposition
でスライドで遷移した際の番号を受け取れるので番号に応じた遷移先のフラグメントを指定します。
class ViewPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
// ページリスト
private val fragments = listOf(
FirstFragment(),
SecondFragment(),
ThirdFragment()
)
// ページの枚数
override fun getItemCount(): Int = fragments.size
// ページの遷移先
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
アダプターの紐付け
最後にviewPager2
にアダプターを紐付けすれば完成です。これでスライドするとフラグメントが滑らかに切り替わる実装が完了しました。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var viewPager: ViewPager2 = findViewById(R.id.pager)
val pagerAdapter = ViewPagerAdapter(this)
viewPager.adapter = pagerAdapter
}
コードでページを遷移する
スワイプだけでなくKotlinのコードからページを遷移させるにはsetCurrentItem
メソッドに遷移させたいページのインデックスを渡します。2つ目の引数smoothScroll
には遷移時に滑らかにスクロールさせるかどうかを真偽値で指定します。
viewPager.setCurrentItem(0, true)
スワイプでのページングを不可にする
ViewPager2
で意図的にスワイプしてもページングをさせないようにするにはisUserInputEnabled
プロパティにfalse
を渡すだけです。
viewPager2.isUserInputEnabled = false
TabLayoutと併用する
TabLayout
と併用することでページのタブを表示することが可能になります。
activity_main.xml
<LinearLayout 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"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed" />
</LinearLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var viewPager: ViewPager2
private lateinit var tabLayout: TabLayout
private lateinit var pagerAdapter: ViewPagerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewPager = findViewById(R.id.pager)
pagerAdapter = ViewPagerAdapter(this)
viewPager.adapter = pagerAdapter
tabLayout = findViewById(R.id.tabLayout)
// TabLayoutMediatorを使用してページングをセットアップ
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
// タブのテキストを設定
tab.text = "Page ${(position + 1)}"
}.attach()
}
}
リスナーを追加する
ページがスワイプされたことや遷移したことを検知するためにはregisterOnPageChangeCallback
メソッドでViewPager2.OnPageChangeCallback
を拡張したオブジェクトを生成し、その中からそれぞれのイベントを検知することが可能です。
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// ページが選択されたときの処理
Log.i("viewPager", "ページが選択")
}
override fun onPageScrollStateChanged(state: Int) {
// ページのスクロール状態が変化したときの処理
Log.i("viewPager", "ページのスクロール状態が変化")
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// ページがスクロールされたときの処理
Log.i("viewPager", "ページがスクロールされた")
}
})
実際に1回だけ横にスワイプしてみると以下のように「ページが選択」は1回しか呼ばれないようですが、他のログは複数回出力されたので使い方には注意が必要かもしれません。
ページのスクロール状態が変化
ページがスクロールされた
ページがスクロールされた
ページがスクロールされた
ページのスクロール状態が変化
ページがスクロールされた
〜〜〜〜〜〜〜〜〜〜〜 × 10くらい
ページがスクロールされた
ページのスクロール状態が変化
RTLのサポート
RTL(右から左)をサポートしたい場合はViewPager2
に
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layoutDirection="rtl"
android:layout_width="match_parent"
android:layout_height="match_parent" />
スライドを縦にする
スライドを縦にしたい場合はViewPager2
に
<androidx.viewpager2.widget.ViewPager2
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。