#はじめに
ViewPager2を実装する際、今までは複数のViewに対してその同数レイアウトファイルを作成していました。
今回は一つのレイアウトファイルで表示できたので紹介します。
ViewPager2実装するのが初めての方にもTabLayoutMediator
とFragmentManager
を理解する助けになればと思います。
全体を見たい方向けにサンプルのリポジトリ載せときます。
https://github.com/tomoya-s-101/viewpager2
#環境
OS: macOS Catalina v10.15.6
IDE: Android Studio v4.0.1
#導入
TabLayoutを使用できるようにするために、build.gradleにmaterial-componentsライブラリを追加します。
implementation "androidx.viewpager2:viewpager2:1.1.0-alpha01"
implementation 'com.google.android.material:material:1.2.0'
#実装
今回は一つのフラグメントレイアウトで画像の色とテキストの切り替えをViewPager2を使い表示します。
##レイアウト
bindingの実装をしたいので、layoutタグで囲います。
tabIndicatorGravityでインジケーターの位置を指定できます。
TabLayoutリファレンス
<?xml version="1.0" encoding="utf-8"?>
<layout>
<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=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
app:tabIndicatorGravity="stretch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/tab_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
ViewPager2で表示するレイアウトを作ります。
stringとcolorのリソースも準備してください。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fragment_color"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tab_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TabTextView"
android:textColor="@color/white"
android:textSize="48sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
##Fragment
表示させたいリストのインスタンスを生むことで、一つのレイアウトで切り替えが可能になります。
class ColorFragment: Fragment() {
companion object {
private const val ARGS_POSITION = "position"
fun newInstance (position: Int) = ColorFragment().apply {
arguments = Bundle().apply {
putInt(ARGS_POSITION, position)
}
}
}
private lateinit var binding: FragmentColorBinding
private val position: Int by lazy {
arguments?.let {
it[ARGS_POSITION] as Int
}?:0
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_color, container, false)
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
binding.apply {
when(position) {
0 -> {
tabTextView.setText(R.string.text_red)
fragmentColor.setBackgroundResource(R.color.red)
}
1 -> {
tabTextView.setText(R.string.text_blue)
fragmentColor.setBackgroundResource(R.color.blue)
}
2 -> {
tabTextView.setText(R.string.text_green)
fragmentColor.setBackgroundResource(R.color.green)
}
else -> {
tabTextView.setText(R.string.text_yellow)
fragmentColor.setBackgroundResource(R.color.yellow)
}
}
}
}
}
##Adapter
FragmentActivityを使用するため、FragmentManager
を呼び出します。
FragmentManagerリファレンス
class ViewPager2Adapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {
private val fragments: ArrayList<Fragment> = arrayListOf(
ColorFragment.newInstance(0),
ColorFragment.newInstance(1),
ColorFragment.newInstance(2),
ColorFragment.newInstance(3)
)
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
##Activity
TabLayoutMediator
でTabLaoutとViewPager2を引数で渡すことで、スクロールとインジケーターがリンクします。
TabLayoutMediatorリファレンス
class MainActivity : AppCompatActivity() {
companion object {
fun callingIntent(context: Context) = Intent(context, MainActivity::class.java)
}
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityMainBinding>(
this, R.layout.activity_main
).apply {
viewpager2.adapter = ViewPager2Adapter(supportFragmentManager, lifecycle)
TabLayoutMediator(tabLayout, viewpager2) { tab, position ->
}.attach()
}
}
}
#おわりに
他にもViewPager2では、縦方向のスクロールなどアクティブな実装が簡単にできるみたいです。
ドキュメント
閲覧ありがとうございました。
2020年7月からエンジニアとして働き始めた見習いですので、拙い点ございます。
間違いやより適切な方法ありましたら、コメントお願いします。
今後も記事を投稿していくので、是非よろしくお願い致します。
#参考
https://developer.android.com/reference/com/google/android/material/tabs/TabLayout
https://developer.android.com/reference/kotlin/androidx/fragment/app/FragmentManager?hl=ja
https://developer.android.com/reference/com/google/android/material/tabs/TabLayoutMediator
https://developer.android.com/training/animation/vp2-migration?hl=ja