Android ViewPager2 & TabLayout

原文地址:itnext.io/android-vie…html

1_PkV1OXoU-hTlejiU4BD7vQ.gif

ViewPager2是在2019年Google I/O大會推出的用來替代ViewPager的,它包含了一些新的特性以及加強了UI和代碼的體驗。java

  1. 從右到左佈局的支持
  2. 垂直方向的滑動
  3. 可變的Fragment集合

image.png

ViewPager2是由RecyclerView支持的ViewGroup,ViewPager2須要一個adapter用來顯示內容,adapter能夠是RecyclerView.Adapter 或者FragmentStateAdapter。android

本文主要介紹ViewPager2的基本使用以及配合TabLayout的使用方法。git

設置

ViewPager2包含在AndroidX library of JetPack中,因此須要單獨引入。github

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'
}
複製代碼

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: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>
複製代碼

定義RecyclerView Adapter和單元佈局

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() = 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)
}
複製代碼
<?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"/>
複製代碼

使用ViewPager2 綁定RecyclerView Adapter

class ViewPager2Activity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_view_pager_demo)
        viewpager.adapter = DemoViewPagerAdapter()
    }
}
複製代碼

TabLayout 沒法與 ViewPager2綁定bash

image.png

可是在StackOverFlow中找到了解決方案,咱們能夠使用TabLayoutMediator實現TabLayout與ViewPager2的綁定。app

image.png

TabLayoutMediator不能直接使用,因此須要拷貝一份出來,根據代碼註釋可知TabLayoutMediator只能在初始化以後才能調用attach方法:ide

image.png

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()
    }
}
複製代碼

TabLayoutMediator.OnConfigureTabCallback是一個用戶友好的方法,在初始化TabLayout.Tab或數據更改是調用:佈局

image.png

RecyclerView adapter Vs FragmentStateAdapter

image.png

ViewPager2能夠接受RecyclerView Adapter 和 FragmentStateAdapter,二者的區別就是RecyclerView Adapter inflate View,而FragmentStateAdapter inflate Fragment。post

當ViewPager2中的每一個頁面用於顯示靜態信息時,當必須考慮頁面的生命週期時,能夠使用FragmentStateAdapter。

集成TabLayout

TabLayout與舊版ViewPager集成在一塊兒很簡單,只需將其添加爲ViewPager的子項,並按設置layout_gravity屬性就能夠了。

<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>
複製代碼

然而,ViewPager2不接受TabLayout做爲子View綁定。

image.png

結論

  1. ViewPager2使用RecyclerView實現,使編碼更加容易
  2. ViewPager2不支持與TabLayout直接綁定,能夠使用TabLayoutMediator來實現。
  3. ViewPager2經過adapter來控制每頁顯示的內容,能夠使用RecyclerView Adapter或者是FragmentStateAdapter
  4. ViewPager2不容許添加任何子View,TabLayout必須與ViewPager2一塊兒放在另外一個ViewGroup中。

擴展閱讀

  1. ViewPager2 with pretty page margin
  2. 4-steps-to-android-dot-tabitem
  3. android-tablayout-and-tabitem
相關文章
相關標籤/搜索