优雅地使用Android ViewPager2

ViewPager2 是 ViewPager 库的改进版本,可提供增强型功能并解决使用 ViewPager 时遇到的一些问题

ViewPager有两个弊端:1.不能关闭预加载;2.更新adapter不生效
我们在加载数据的时候,viewpager默认会帮我们预加载前后两个页面的数据,并且这2个view是不可见的。而目前ViewPager2对Fragment支持只能用FragmentStateAdapter,FragmentStateAdapter在遇到预加载时,只会创建Fragment对象,不会把Fragment真正的加入到布局中,所以自带懒加载效果

Android ViewPager2的特性

(1)垂直方向支持,可以通过设置 ViewPager2 元素的 android:orientation 属性为其启用垂直分页
(2)从右到左支持,系统会根据语言区域在适当的情况下自动启用 RTL 分页,也可以通过设置 ViewPager2 元素的 android:layoutDirection 属性为其手动启用 RTL 分页
(3)更高效的notifyDataSetChanged,在运行时动态修改 Fragment 集合,而 ViewPager2 会正确显示修改后的集合

简单使用

(1)导入依赖:

    implementation "com.google.android.material:material:1.2.1"

(2)activity_main.xml


<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"
        app:tabGravity="fill"
        app:tabIndicatorColor="@android:color/holo_blue_light"
        app:tabIndicatorHeight="2dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@android:color/holo_blue_light"
        app:tabTextColor="@android:color/black" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

LinearLayout>

(3)MainActivity

class MainActivity : AppCompatActivity() {
     
    private var fragmentList: MutableList<Fragment>? = null
    private val title = arrayOf("海贼王", "火影忍者", "七龙珠")
    override fun onCreate(savedInstanceState: Bundle?) {
     
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        init()
    }

    private fun init() {
     
        fragmentList = ArrayList()
        fragmentList!!.add(OneFragment())
        fragmentList!!.add(TwoFragment())
        fragmentList!!.add(ThreeFragment())
        viewPager.adapter = MyFragmentStateAdapter(this, fragmentList!!)
        viewPager.setPageTransformer(ZoomOutPageTransformer())//设置页面切换的动画
        //TabLayout与ViewPager2联动
        TabLayoutMediator(tabLayout, viewPager) {
      tab, position ->
            tab.text = title[position]
        }.attach()
    }
}

可以设置viewPager.isUserInputEnabled = false禁用页面滑动
TabLayout可以设置app:tabIndicatorFullWidth=“false”,使其下划线的宽度随着字的宽改变而改变

(4)MyFragmentStateAdapter

class MyFragmentStateAdapter(fragmentActivity: FragmentActivity, private val list: List<Fragment>) :
    FragmentStateAdapter(fragmentActivity) {
     
    override fun createFragment(position: Int): Fragment {
     
        return list[position]
    }

    override fun getItemCount(): Int {
     
        return list.size
    }
}

(5)Fragment切换的动画

private const val MIN_SCALE = 0.85f
private const val MIN_ALPHA = 0.5f

class ZoomOutPageTransformer : ViewPager2.PageTransformer {
     

    override fun transformPage(view: View, position: Float) {
     
        view.apply {
     
            val pageWidth = width
            val pageHeight = height
            when {
     
                position < -1 -> {
     
                    alpha = 0f
                }
                position <= 1 -> {
     
                    val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position))
                    val vertMargin = pageHeight * (1 - scaleFactor) / 2
                    val horzMargin = pageWidth * (1 - scaleFactor) / 2
                    translationX = if (position < 0) {
     
                        horzMargin - vertMargin / 2
                    } else {
     
                        horzMargin + vertMargin / 2
                    }
                    scaleX = scaleFactor
                    scaleY = scaleFactor
                    alpha = (MIN_ALPHA +
                            (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)))
                }
                else -> {
     
                    alpha = 0f
                }
            }
        }
    }
}

如果你想实现底部导航栏,用法也差不多
修改布局文件


<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">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabGravity="fill"
        app:tabIndicatorColor="@android:color/holo_blue_light"
        app:tabIndicatorHeight="2dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@android:color/holo_blue_light"
        app:tabTextColor="@android:color/black" />

LinearLayout>

修改Activity的代码

class BottomActivity : AppCompatActivity() {
     
    private var fragmentList: MutableList<Fragment>? = null
    private val title = arrayOf("首页", "位置", "我的")

    override fun onCreate(savedInstanceState: Bundle?) {
     
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_bottom)
        init()
    }

    private fun init() {
     
        fragmentList = ArrayList()
        fragmentList!!.add(OneFragment())
        fragmentList!!.add(TwoFragment())
        fragmentList!!.add(ThreeFragment())
        //设置底部导航图标
        val icon = arrayListOf(
            ContextCompat.getDrawable(this, R.drawable.home_grey)!!,
            ContextCompat.getDrawable(this, R.drawable.add_grey)!!,
            ContextCompat.getDrawable(this, R.drawable.me_grey)!!
        )
        val iconSelected = arrayListOf(
            ContextCompat.getDrawable(this, R.drawable.home_blue)!!,
            ContextCompat.getDrawable(this, R.drawable.add_blue)!!,
            ContextCompat.getDrawable(this, R.drawable.me_blue)!!
        )
        view_pager.adapter = MyFragmentStateAdapter(this, fragmentList!!)
        view_pager.setPageTransformer(ZoomOutPageTransformer())
        tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
     
            override fun onTabSelected(tab: TabLayout.Tab?) {
     
                tab!!.icon = iconSelected[tab.position]
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
     
                tab!!.icon = icon[tab.position]
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {
     

            }

        })
        view_pager.isUserInputEnabled = false //禁用页面滑动
        //TabLayout与ViewPager2联动
        TabLayoutMediator(tab_layout, view_pager) {
      tab, position ->
            tab.text = title[position]
            tab.icon = icon[position]
        }.attach()

    }
}

你可能感兴趣的:(优雅地使用Android ViewPager2)