ViewPager2 是 ViewPager 库的改进版本,提供

增强的功能,并解决了使用 ViewPager 时的常见难题。

如果您的应用已在使用 ViewPager,请阅读此页面,详细了解

迁移到 ViewPager2。

如果您想在应用中使用 ViewPager2,但目前未使用

ViewPager,请参阅使用“在 fragment 之间滑动”

ViewPager2 和使用以下代码创建滑动视图

使用 ViewPager2 的标签页了解详情

信息。

迁移到 ViewPager2 的优势

迁移的主要原因是“ViewPager2”正在接收有效消息

开发支持,ViewPager 不提供支持。不过,ViewPager2还提供

还有其他一些具体优势

垂直方向支持

除了传统的水平分页之外,ViewPager2 还支持垂直分页

分页。您可以为 ViewPager2 元素启用垂直分页,只需设置其

android:orientation 属性:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/pager"

android:orientation="vertical" />

您还可以使用

setOrientation()

方法。

从右到左支持

ViewPager2 支持从右到左 (RTL) 分页。已启用 RTL 分页

根据语言区域在适当的时候自动进行更新,但您也可以手动

通过设置 ViewPager2 元素的 RTL 分页,

android:layoutDirection 属性:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/pager"

android:layoutDirection="rtl" />

您还可以使用

setLayoutDirection()

方法。

可修改的 Fragment 集合

ViewPager2 支持对可修改的 fragment 集合进行分页;

呼叫

notifyDatasetChanged()

在底层集合发生更改时更新界面。

这意味着您的应用可以在

运行时,ViewPager2 会正确显示修改后的集合。

DiffUtil

ViewPager2 基于 RecyclerView 构建,

这意味着它有权访问

DiffUtil 实用程序

类。这带来了很多好处,但最值得注意的是,这意味着

ViewPager2 对象本身会利用数据集更改动画

。RecyclerView

将您的应用迁移到 ViewPager2

请按照以下步骤将应用中的 ViewPager 对象更新为 ViewPager2:

更新 XML 布局文件

首先,将 XML 布局文件中的 ViewPager 元素替换为

ViewPager2 元素:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/pager"

android:layout_width="match_parent"

android:layout_height="match_parent" />

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/pager"

android:layout_width="match_parent"

android:layout_height="match_parent" />

更新适配器类

使用 ViewPager 时,您必须扩展适配器类,

为对象提供的新页面。根据用例,使用 ViewPager

三个不同的抽象类。ViewPager2 只使用两个抽象类。

对于要转换为 ViewPager2 对象的每个 ViewPager 对象,

更新适配器类以扩展相应的抽象类,如下所示:

当 ViewPager 使用 PagerAdapter 对视图进行分页时,请使用

RecyclerView.Adapter 和 ViewPager2。

当ViewPager使用FragmentPagerAdapter浏览一个小网页时,

固定数量的 fragment,请将 FragmentStateAdapter 与 ViewPager2 搭配使用。

当ViewPager使用FragmentStatePagerAdapter浏览

大量或未知的 fragment,请使用 FragmentStateAdapter 和

ViewPager2。

构造函数参数

基于 Fragment 的适配器类,继承自 FragmentPagerAdapter 或

FragmentStatePagerAdapter 始终接受单个 FragmentManager 对象

作为构造函数参数。当您将 FragmentStateAdapter 扩展为

ViewPager2 适配器类,对于构造函数,您有以下选择:

参数:

FragmentActivity 对象或 Fragment 对象,

ViewPager2 对象所处的位置。在大多数情况下,这个选择更好。

FragmentManager 对象和 Lifecycle 对象。

直接从 RecyclerView.Adapter 继承的基于视图的适配器类会

不需要构造函数参数。

替换方法

您的适配器类还需要为 ViewPager2 替换不同的方法

相比ViewPager:

替换 getItemCount(),而不是 getCount()。除了名称之外

此方法保持不变。

在基于 fragment 中替换 createFragment(),而不是 getItem()

适配器类。确保新的 createFragment() 方法始终

每次调用函数时都会提供新的 fragment 实例,而不是

和重复使用实例

注意: DiffUtil 实用程序类依赖于按 ID 标识项目。如果

使用 ViewPager2 对可变集合进行分页时,还必须

替换 getItemId() 和 containsItem()。

此外,不支持将 getPageWidth() 方法用于

ViewPager2。如果您目前将 getPageWidth() 与 ViewPager 搭配使用,以启用

必须改用 clipToPadding

RecyclerView 的属性,如示例应用所示。

摘要

总而言之,如需转换 ViewPager 适配器类以与 ViewPager2 搭配使用,

您必须进行以下更改:

将父类更改为 RecyclerView.Adapter 以对视图进行分页,或

FragmentStateAdapter,用于对 fragment 进行分页。

更改基于 Fragment 的适配器类中的构造函数参数。

替换 getItemCount(),而不是 getCount()。

在基于 fragment 的适配器中替换 createFragment(),而不是 getItem()

类。

Kotlin

// A simple ViewPager adapter class for paging through fragments

class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {

override fun getCount(): Int = NUM_PAGES

override fun getItem(position: Int): Fragment = ScreenSlidePageFragment()

}

// An equivalent ViewPager2 adapter class

class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {

override fun getItemCount(): Int = NUM_PAGES

override fun createFragment(position: Int): Fragment = ScreenSlidePageFragment()

}

Java

// A simple ViewPager adapter class for paging through fragments

public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {

public ScreenSlidePagerAdapter(FragmentManager fm) {

super(fm);

}

@Override

public Fragment getItem(int position) {

return new ScreenSlidePageFragment();

}

@Override

public int getCount() {

return NUM_PAGES;

}

}

// An equivalent ViewPager2 adapter class

private class ScreenSlidePagerAdapter extends FragmentStateAdapter {

public ScreenSlidePagerAdapter(FragmentActivity fa) {

super(fa);

}

@Override

public Fragment createFragment(int position) {

return new ScreenSlidePageFragment();

}

@Override

public int getItemCount() {

return NUM_PAGES;

}

}

重构 TabLayout 接口

ViewPager2 引入了对 TabLayout 集成的更改。如果您

目前使用 ViewPager 和 TabLayout 对象显示水平方向

进行导航时,您需要重构 TabLayout 对象

与 ViewPager2 集成。

TabLayout 已与 ViewPager2 分离,现在作为

Material 组件。也就是说,要使用它,您需要将

与 build.gradle 文件添加适当的依赖项:

Groovy

implementation "com.google.android.material:material:1.1.0-beta01"

Kotlin

implementation("com.google.android.material:material:1.1.0-beta01")

您还需要更改 TabLayout 元素在

XML 布局文件使用 ViewPager 时,TabLayout 元素声明为

ViewPager 元素的子元素;但使用 ViewPager2 时,TabLayout 元素

在同一级别上直接声明在 ViewPager2 元素的上方:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/pager"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/tab_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/tab_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/pager"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" />

最后,您必须更新用于将 TabLayout 对象附加到

ViewPager 对象。而 TabLayout 使用自己的 setupWithViewPager()

方法与 ViewPager 集成,则需要 TabLayoutMediator

实例与 ViewPager2 集成。

TabLayoutMediator 对象还可处理生成网页标题的任务

(针对 TabLayout 对象),这意味着适配器类无需

替换 getPageTitle():

Kotlin

// Integrating TabLayout with ViewPager

class CollectionDemoFragment : Fragment() {

...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

val tabLayout = view.findViewById(R.id.tab_layout)

tabLayout.setupWithViewPager(viewPager)

}

...

}

class DemoCollectionPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {

override fun getCount(): Int = 4

override fun getPageTitle(position: Int): CharSequence {

return "OBJECT ${(position + 1)}"

}

...

}

// Integrating TabLayout with ViewPager2

class CollectionDemoFragment : Fragment() {

...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

val tabLayout = view.findViewById(R.id.tab_layout)

TabLayoutMediator(tabLayout, viewPager) { tab, position ->

tab.text = "OBJECT ${(position + 1)}"

}.attach()

}

...

}

Java

// Integrating TabLayout with ViewPager

public class CollectionDemoFragment extends Fragment {

...

@Override

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

TabLayout tabLayout = view.findViewById(R.id.tab_layout);

tabLayout.setupWithViewPager(viewPager);

}

...

}

public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {

...

@Override

public int getCount() {

return 4;

}

@Override

public CharSequence getPageTitle(int position) {

return "OBJECT " + (position + 1);

}

...

}

// Integrating TabLayout with ViewPager2

public class CollectionDemoFragment : Fragment() {

...

@Override

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

TabLayout tabLayout = view.findViewById(R.id.tab_layout);

new TabLayoutMediator(tabLayout, viewPager,

(tab, position) -> tab.setText("OBJECT " + (position + 1))

).attach();

}

...

}

支持嵌套的可滚动元素

ViewPager2 本身不支持嵌套滚动视图,

滚动视图的方向与包含ViewPager2

。例如,滚动操作在

垂直方向的 ViewPager2 对象。

如需支持 ViewPager2 对象内具有相同方向的滚动视图,

您必须调用

针对 ViewPager2 对象执行 requestDisallowInterceptTouchEvent() 操作

应改为滚动嵌套元素。ViewPager2 嵌套滚动

示例演示了一种使用多种多样的

自定义封装容器布局。

其他资源

如需详细了解 ViewPager2,请参阅下面列出的其他资源。

示例

GitHub 上的 ViewPager2 示例

视频

新篇章:迁移到 ViewPager2(2019 年 Android 开发者峰会)

Copyright © 2088 1986世界杯_意大利世界杯 - zlrxcw.com All Rights Reserved.
友情链接