一、缘起:
ViewPager2推出已经有一段时间了,而且官方推出了稳定版本Version 1.0.0,相比ViewPager增加了很多优势,是时候用起来了。
二、优势
1、垂直方向支持
- ViewPager2 支持垂直分页
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
- 代码动态设置方式
// 水平方向
viewpager_two.orientation=ViewPager2.ORIENTATION_HORIZONTAL
// 垂直方向
viewpager_two.orientation=ViewPager2.ORIENTATION_VERTICAL
ps:之前使用VerticalViewpager现在可以改为ViewPager2了
2、从右到左支持
- 默认为从左到右滑动方向,可以通过设置layoutDirection="rtl"设置为从右到左滑动
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="rtl"/>
3、可修改的 Fragment 集合
ViewPager2 支持对可修改的 Fragment 集合进行分页浏览,在底层集合发生更改时调用 notifyDatasetChanged() 来更新界面。
4、DiffUtil
ViewPager2 在 RecyclerView 的基础上构建而成,这意味着它可以访问 DiffUtil 实用程序类。这一点带来了多项优势,但最突出的一项是,这意味着 ViewPager2 对象本身会利用 RecyclerView 类中的数据集更改动画。
三、使用实例
1、添加依赖
- build.gradle中
dependencies {
implementation "androidx.viewpager2:viewpager2:1.0.0"
}
2、水平滑动 不指定方向为水平滑动
- 水平滑动从左到右方向
- xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
- adapter
class ViewpagerTwoAdapter : RecyclerView.Adapter<ViewpagerTwoAdapter.MyHolder>() {
private val imgArray = intArrayOf(R.drawable.dog_01, R.drawable.dog_02, R.drawable.dog_03)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
return MyHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_view_pager2, parent, false)
)
}
override fun getItemCount(): Int {
return 10
}
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.ivItem.setImageResource(imgArray[position % imgArray.size])
}
class MyHolder(view: View) : RecyclerView.ViewHolder(view) {
val ivItem: ImageView = view.findViewById(R.id.iv_item)
}
}
- 效果图
- 水平滑动从右到左方向
- 添加方向指定 android:layoutDirection=“rtl”
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layoutDirection="rtl"
/>
- 效果图
3、垂直方向滑动
- 只需指定android:orientation="vertical"即可
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"/>
- 效果图
4、结合Fragment使用
- activity代码
// 结合fragment使用
viewpager_two.adapter = FragmentViewPagerTwoAdapter(this)
- adapter 继承FragmentStateAdapter
class FragmentViewPagerTwoAdapter(frag:FragmentActivity) :FragmentStateAdapter(frag){
override fun getItemCount(): Int {
return 5
}
override fun createFragment(position: Int): Fragment {
return NormalFragment()
}
}
- Fragment代码
class NormalFragment :Fragment(){
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_normal, container, false)
}
}
- fragment_normal xml文件
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_fragment_normal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/dog_01"/>
</androidx.constraintlayout.widget.ConstraintLayout>
- 效果图
Fragment也可以设置为垂直滑动和从右到左水平滑动,只需根据需要设置orientation和layoutDirection即可
5、结合TabLayout使用
- 添加依赖
implementation "com.google.android.material:material:1.1.0-beta01"
- 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/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_two"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
- activity调用代码
// 结合tableLayout使用
TabLayoutMediator(tab_layout, viewpager_two) { tab, position ->
tab.text = "Tab ${(position + 1)}"
}.attach()
一定要调用attach()方法才起作用
- 效果图
6、实现ViewPager2.PageTransformer自定义切换效果,设置切换效果
放大进入效果
- activity代码
viewpager_two.setPageTransformer(ZoomPagerTransformer())
- ZoomPagerTransformer
private const val MIN_SCALE = 0.85f
private const val MIN_ALPHA = 0.5f
class ZoomPagerTransformer :ViewPager2.PageTransformer{
override fun transformPage(view: View, position: Float) {
view.apply {
val pageWidth = width
val pageHeight = height
when {
position < -1 -> { // [-Infinity,-1)
// This page is way off-screen to the left.
alpha = 0f
}
position <= 1 -> { // [-1,1]
// Modify the default slide transition to shrink the page as well
val scaleFactor = MIN_SCALE.coerceAtLeast(1 - 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
}
// Scale the page down (between MIN_SCALE and 1)
scaleX = scaleFactor
scaleY = scaleFactor
// Fade the page relative to its size.
alpha = (MIN_ALPHA +
(((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)))
}
else -> { // (1,+Infinity]
// This page is way off-screen to the right.
alpha = 0f
}
}
}
}
}
- 效果图
层次进入效果
- activity代码
viewpager_two.setPageTransformer(DepthPageTransformer())
- DepthPageTransformer
private const val MIN_SCALE = 0.75f
class DepthPageTransformer : ViewPager2.PageTransformer {
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun transformPage(view: View, position: Float) {
view.apply {
val pageWidth = width
when {
position < -1 -> { // [-Infinity,-1)
// This page is way off-screen to the left.
alpha = 0f
}
position <= 0 -> { // [-1,0]
// Use the default slide transition when moving to the left page
alpha = 1f
translationX = 0f
translationZ = 0f
scaleX = 1f
scaleY = 1f
}
position <= 1 -> { // (0,1]
// Fade the page out.
alpha = 1 - position
// Counteract the default slide transition
translationX = pageWidth * -position
// Move it behind the left page
translationZ = -1f
// Scale the page down (between MIN_SCALE and 1)
val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)))
scaleX = scaleFactor
scaleY = scaleFactor
}
else -> { // (1,+Infinity]
// This page is way off-screen to the right.
alpha = 0f
}
}
}
}
}
- 效果图
使用CompositePageTransformer实现多个transformer合并使用
- activity代码
// 多个transformer结合使用
val compositePageTransformer = CompositePageTransformer()
compositePageTransformer.addTransformer(DepthPageTransformer())
// marginTransformer
compositePageTransformer.addTransformer(MarginPageTransformer(10))
viewpager_two.setPageTransformer(compositePageTransformer)
- 效果图