Itnext. IO/Android-vie…

ViewPager2 was introduced at Google I/O 2019 to replace ViewPager and includes several new features and enhanced UI and code experiences.

  1. Right-to-left layout support
  2. Vertical sliding
  3. Mutable Fragment collection

ViewPager2 is a ViewGroup supported by RecyclerView. ViewPager2 requires a recyclerview. adapter or FragmentStateAdapter to display content.

This paper mainly introduces the basic use of ViewPager2 and TabLayout with the use of methods.

Set up the

ViewPager2 is included in the AndroidX Library of JetPack, so it needs to be introduced separately.

dependencies {
     // For the latest version number of ViewPager2, please refer to the official page.
     // Link: https://developer.android.com/jetpack/androidx/releases/viewpager2
     implementation 'androidx. Viewpager2: viewpager2:1.0.0 - alpha04'
}
Copy the code

XML layout

<? 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:orientation="vertical">

    <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="240dp"/>
</LinearLayout>
Copy the code

Define RecyclerView Adapter and cell layout

class DemoViewPagerAdapter : RecyclerView.Adapter<DemoViewPagerAdapter.EventViewHolder>() {
    val eventList = listOf("0"."1"."2")

    // Layout "layout_demo_viewpager2_cell.xml" will be defined later
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        EventViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_demo_viewpager2_cell, parent, false))

    override fun getItemCount(a) = eventList.count()
    override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
        (holder.view as? TextView)? .also{ it.text ="Page " + eventList.get(position)
            
            val backgroundColorResId = if (position % 2= =0) R.color.blue else R.color.orange)
            it.setBackgroundColor(ContextCompat.getColor(it.context, backgroundColorResId))
        }
    }

    class EventViewHolder(val view: View) : RecyclerView.ViewHolder(view)
}
Copy the code
<? xml version="1.0" encoding="utf-8"? > <TextView xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:textSize="20sp"
       android:gravity="center"/>
Copy the code

Use ViewPager2 to bind RecyclerView Adapter

class ViewPager2Activity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_view_pager_demo)
        viewpager.adapter = DemoViewPagerAdapter()
    }
}
Copy the code

TabLayout cannot be bound to ViewPager2

The solution, however, was found in StackOverFlow. We could use TabLayoutMediator to bind TabLayout to ViewPager2.

TabLayoutMediator cannot be used directly, so it needs to be copied. The Attach method can only be called after the attach method is initialized.

class ViewPager2Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view_pager2)
        
        // Must be declared before TabLayoutMediator.attach()
        viewpager.adapter = DemoViewPagerAdapter()
        TabLayoutMediator(tabLayout, viewpager, object : TabLayoutMediator.OnConfigureTabCallback {
            override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
                // Styling each tab here
                tab.setText("Tab $position")
            }
        }).attach()
    }
}
Copy the code

TabLayoutMediator OnConfigureTabCallback is a user friendly way, in the initialization TabLayout. Tab or data changes is called:

RecyclerView adapter Vs FragmentStateAdapter

ViewPager2 can accept RecyclerView adapters and FragmentState Adapters. The difference between the two is that the RecyclerView Adapter inflate View, And FragmentStateAdapter Inflate Fragment.

When each page in ViewPager2 is used to display static information, you can use a FragmentStateAdapter when you must consider the life cycle of the page.

Integrated TabLayout

Integrating TabLayout with the older ViewPager is as simple as adding it as a child of the ViewPager and pressing the set layout_gravity property.

<android.support.v4.view.ViewPager
     android:layout_width="match_parent"
     android:layout_height="match_parent">
     <android.support.design.widget.TabLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="top" />
 </android.support.v4.view.ViewPager>
Copy the code

However, ViewPager2 does not accept TabLayout as a child View binding.

conclusion

  1. ViewPager2 use RecyclerView implementation, make coding easier
  2. ViewPager2 does not support binding directly to TabLayout. It can be implemented using TabLayoutMediator.
  3. ViewPager2 uses a RecyclerView adapter or FragmentStateAdapter to control the content displayed on each page
  4. ViewPager2 does not allow any child views to be added, and TabLayout must be placed in another ViewGroup with ViewPager2.

Further reading

  1. ViewPager2 with pretty page margin
  2. 4-steps-to-android-dot-tabitem
  3. android-tablayout-and-tabitem