ViewPager2原理解析,2024年最新社招测试开发面试题

initialize方法里面,主要初始化RecyclerView的基本配置和基本组件。在这个方面,做了两件比较重要的事情:1. 给RecyclerView设置了滑动监听事件,涉及到的组件是ScrollEventAdapter,后面的基本功能都需要这个组件的支持;2. 设置了PagerSnapHelper,目的是实现切面切换的效果。

我们对ViewPager2有了基本的了解之后,现在就来对各个组件进行详细的分析。

4. PagerSnapHelper

==============================================================================

RecyclerView 源码分析(七) - 自定义LayoutManager及其相关组件的源码分析文章里面,我已经简单分析过SnapHelper。我们知道SnapHelper最重要的三个方法是:calculateDistanceToFinalSnapfindSnapViewfindTargetSnapPosition

为了更好区分这三个方法的不同点,我以一个非常常用的场景来描述这三个方法的调用,分别分为如下三个阶段:

  1. 假设手指在快速滑动一个RecyclerView,在手指离开屏幕之前,如上的三个方法都不会被调用。
  1. 而此时如果手指如果手指离开了屏幕,接下来就是Fling事件来滑动RecyclerView,在Fling事件触发之际,findTargetSnapPosition方法会被调用,此方法的作用就是用来计算Fling事件能滑动到位置。
  1. 当Fling事件结束之际,RecyclerView会回调SnapHelper内部OnScrollListener接口的onScrollStateChanged方法。此时RecyclerView的滑动状态为RecyclerView.SCROLL_STATE_IDLE,所以就会分别调用findSnapView方法来找到需要显示在RecyclerView的最前面的View。找到目标View之后,就会调用calculateDistanceToFinalSnap方法来计算需要滑动的距离,然后调动RecyclerView相关方法进行滑动。

正常来说,当RecyclerView在Fling时,如果想要不去拦截Fling时间,想让RecyclerView开心的Fling,可以直接在findTargetSnapPosition方法返回RecyclerView.NO_POSITION即可,从而将Fling事件交给RecyclerView,或者我们可以在findTargetSnapPosition方法来计算滑动的最终位置,然后通过SmoothScroller来实现滑动。

但是,我们知道PagerSnapHelper不支持Fling事件,所以在PagerSnapHelper内部,必须实现findTargetSnapPosition方法,从而避免RecyclerViewFling。

(1). findTargetSnapPosition方法

熟悉PagerSnapHelper的基本知识之后,现在我们来重点分析这三个方法,我们先来看看findTargetSnapPosition方法,看看它是怎么阻止RecyclerView的Fling事件。

@Override

public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX,

int velocityY) {

// ······

// 找到与当前View相邻的View,包括左相邻和右响铃,并且计算滑动的距离

for (int i = 0; i < childCount; i++) {

final View child = layoutManager.getChildAt(i);

if (child == null) {

continue;

}

final int distance = distanceToCenter(layoutManager, child, orientationHelper);

if (distance <= 0 && distance > distanceBefore) {

// Child is before the center and closer then the previous best

distanceBefore = distance;

closestChildBeforeCenter = child;

}

if (distance >= 0 && distance < distanceAfter) {

// Child is after the center and closer then the previous best

distanceAfter = distance;

closestChildAfterCenter = child;

}

}

// 根据滑动的方向来返回的相应位置

final boolean forwardDirection = isForwardFling(layoutManager, velocityX, velocityY);

if (forwardDirection && closestChildAfterCenter != null) {

return layoutManager.getPosition(closestChildAfterCenter);

} else if (!forwardDirection && closestChildBeforeCenter != null) {

return layoutManager.getPosition(closestChildBeforeCenter);

}

// 兜底计算

View visibleView = forwardDirection ? closestChildBeforeCenter : closestChildAfterCenter;

if (visibleView == null) {

return RecyclerView.NO_POSITION;

}

int visiblePosition = layoutManager.getPosition(visibleView);

int snapToPosition = visiblePosition

  • (isReverseLayout(layoutManager) == forwardDirection ? -1 : +1);

if (snapToPosition < 0 || snapToPosition >= itemCount) {

return RecyclerView.NO_POSITION;

}

return snapToPosition;

}

从上面的代码中,我们可以非常容易得到一个信息,为了阻止RecyclerView的Fling事件,findTargetSnapPosition方法直接返回当前ItemView的上一个ItemView或者下一个ItemView的位置。所以PagerSnapHelperfindTargetSnapPosition方法还是非常简单的。

那么findTargetSnapPosition方法是怎么阻止Fling事件的触发呢?首先得保证findTargetSnapPosition方法返回的值不为RecyclerView.NO_POSITION,然后我们来看看SnapHelpersnapFromFling方法:

private boolean snapFromFling(@NonNull RecyclerView.LayoutManager layoutManager, int velocityX,

int velocityY) {

if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {

return false;

}

RecyclerView.SmoothScroller smoothScroller = createScroller(layoutManager);

if (smoothScroller == null) {

return false;

}

int targetPosition = findTargetSnapPosition(layoutManager, velocityX, velocityY);

if (targetPosition == RecyclerView.NO_POSITION) {

return false;

}

smoothScroller.setTargetPosition(targetPosition);

layoutManager.startSmoothScroll(smoothScroller);

return true;

}

snapFromFling方法中我们知道,只要findTargetSnapPosition方法返回不为RecyclerView.NO_POSITION,那么接下来的滑动事件会交给SmoothScroller去处理,所以RecyclerView最终滑到的位置为当前位置的上一个或者下一个,不会产生Fling的效果。

(2). findSnapView方法

RecyclerView滑动完毕之后,此时会先调用findSnapView方法获取来最终位置的ItemView。当RecyclerView触发Fling事件时,才会触发findTargetSnapPosition方法,从而保证RecyclerView滑动到正确位置;那么当RecyclerView没有触发Fling事件,怎么保证RecyclerView滑动到正确位置呢?当然是findSnapView方法和calculateDistanceToFinalSnap方法,这俩方法还有一个目的就是,如果Fling没有滑动正确位置,这俩方法可以做一个兜底操作:

public View findSnapView(RecyclerView.LayoutManager layoutManager) {

if (layoutManager.canScrollVertically()) {

return findCenterView(layoutManager, getVerticalHelper(layoutManager));

} else if (layoutManager.canScrollHorizontally()) {

return findCenterView(layoutManager, getHorizontalHelper(layoutManager));

}

return null;

}

findSnapView内部,调用findCenterView方法,我们先来看看findCenterView方法的代码:

private View findCenterView(RecyclerView.LayoutManager layoutManager,

OrientationHelper helper) {

int childCount = layoutManager.getChildCount();

if (childCount == 0) {

return null;

}

View closestChild = null;

final int center;

if (layoutManager.getClipToPadding()) {

center = helper.getStartAfterPadding() + helper.getTotalSpace() / 2;

} else {

center = helper.getEnd() / 2;

}

int absClosest = Integer.MAX_VALUE;

for (int i = 0; i < childCount; i++) {

final View child = layoutManager.getChildAt(i);

int childCenter = helper.getDecoratedStart(child)

  • (helper.getDecoratedMeasurement(child) / 2);

int absDistance = Math.abs(childCenter - center);

/* if child center is closer than previous closest, set it as closest */

if (absDistance < absClosest) {

absClosest = absDistance;

closestChild = child;

}

}

return closestChild;

}

findCenterView方法还是比较长,但是表示的意思非常简单,就是找到当前中心距离屏幕中心最近的ItemView。这个怎么来理解呢?比如说,我们手指在滑动一个页面,滑动到一定距离时就松开了,此时屏幕当中有两个页面,那么ViewPager2应该滑动到哪一个页面呢?当然是距离屏幕中心最近的页面。findCenterView方法的作用便是如此。

(3). calculateDistanceToFinalSnap方法

找到需要滑到的ItemView,此时就应该调用calculateDistanceToFinalSnap方法来计算,此时RecyclerView还需要滑动多少距离才能达到正确位置:

public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,

@NonNull View targetView) {

int[] out = new int[2];

if (layoutManager.canScrollHorizontally()) {

out[0] = distanceToCenter(layoutManager, targetView,

getHorizontalHelper(layoutManager));

} else {

out[0] = 0;

}

if (layoutManager.canScrollVertically()) {

out[1] = distanceToCenter(layoutManager, targetView,

getVerticalHelper(layoutManager));

} else {

out[1] = 0;

}

return out;

}

calculateDistanceToFinalSnap表达的意思非常简单,就是计算RecyclerView需要滑动的距离,主要通过distanceToCenter方法来计算,具体细节我们就不讨论,非常简单,有兴趣的同学可以去看看。

我们从整体上了解了PagerSnapHelper的源码,应该非常容易的知道,为什么PagerSnapHelper可以实现页面切换的效果。我来简单的总结一下:

  1. 首先阻止RecyclerView的Fling事件,阻止的方式就是重写findTargetSnapPosition方法,当RecyclerView触发了Fling事件之后,直接滑动到下一个或者上一个。
  1. 如果RecyclerView没有触发Fling事件,或者Fling阶段未能滑动到正确位置,此时需要findSnapView方法和calculateDistanceToFinalSnap来保证滑动到正确的页面。

5. ScrollEventAdapter

=================================================================================

分析完PagerSnaHelper之后,我们来看看ScrollEventAdapter。前面我们已经说过了,ScrollEventAdapter的作用将RecyclerView的滑动事件转为ViewPager2的页面滑动事件。

在分析源码之前,我们先来看看几个状态:

| 名称 | 含义 |

| — | — |

| STATE_IDLE | 表示当前ViewPager2处于停止状态 |

| STATE_IN_PROGRESS_MANUAL_DRAG | 表示当前ViewPager2处于手指拖动状态 |

| STATE_IN_PROGRESS_SMOOTH_SCROLL | 表示当前ViewPager2处于缓慢滑动的状态。这个状态只在调用了ViewPager2setCurrentItem方法才有可能出现。 |

| STATE_IN_PROGRESS_IMMEDIATE_SCROLL | 表示当前ViewPager2处于迅速滑动的状态。这个状态只在调用了ViewPager2setCurrentItem方法才有可能出现。 |

| STATE_IN_PROGRESS_FAKE_DRAG | 表示当前ViewPager2未使用手指滑动,而是通过FakerDrag实现的。 |

ScrollEventAdapter实现的是OnScrollListener接口,所以,我们的重点放在两个实现方法里面。不过在正式这俩方法之前,我们先来了解几个方法,方便后面的理解。

| 方法名 | 含义 |

| — | — |

| dispatchStateChanged | 将状态改变的信息分发到OnPageChangeCallback监听器,不过需要注意的是:ViewPager2处于停止状态,同时调用了setCurrentItem方法来立即切换到某一个页面(注意,不是缓慢的切换),不会回调OnPageChangeCallback的方法。 |

| dispatchSelected | 分发选中页面的信息。 |

| dispatchScrolled | 分发页面滑动的相关信息。 |

接下来,我们将正式分析onScrollStateChangedonScrolled

(1). onScrollStateChanged方法

RecyclerView的滑动状态发生变化,这个方法就会被调用。这个方法主要分为3个阶段,分别如下:

  1. 开始拖动,会调用startDrag方法表示拖动开始。
  1. 拖动手势的释放,此时ViewPager2会准备滑动到正确的位置。
  1. 滑动结束,此时ScrollEventAdapter会调用相关的方法更新状态。

public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {

// 1. 开始拖动

if (mAdapterState != STATE_IN_PROGRESS_MANUAL_DRAG

&& newState == RecyclerView.SCROLL_STATE_DRAGGING) {

startDrag(false);

return;

}

// 2. 拖动手势的释放

if (isInAnyDraggingState() && newState == RecyclerView.SCROLL_STATE_SETTLING) {

// Only go through the settling phase if the drag actually moved the page

if (mScrollHappened) {

dispatchStateChanged(SCROLL_STATE_SETTLING);

// Determine target page and dispatch onPageSelected on next scroll event

mDispatchSelected = true;

}

return;

}

// 3. 滑动结束

if (isInAnyDraggingState() && newState == RecyclerView.SCROLL_STATE_IDLE) {

boolean dispatchIdle = false;

updateScrollEventValues();

// 如果在拖动期间为产生移动距离

if (!mScrollHappened) {

if (mScrollValues.mPosition != RecyclerView.NO_POSITION) {

dispatchScrolled(mScrollValues.mPosition, 0f, 0);

}

dispatchIdle = true;

} else if (mScrollValues.mOffsetPx == 0) {

dispatchIdle = true;

if (mDragStartPosition != mScrollValues.mPosition) {

dispatchSelected(mScrollValues.mPosition);

}

}

if (dispatchIdle) {

dispatchStateChanged(SCROLL_STATE_IDLE);

resetState();

}

}

}

第1步和第2步我们非常的容易理解,至于第3步我们需要注意如下两点:

  1. dispatchStateChanged方法的调用时机:1. 根本没有滑动,也就是说,onScrolled方法没有被调用;2. 滑动过,并且在上一次滑动中最后一次调用onScrolled方法的时候会被调用。
  1. dispatchSelected方法的调用时机:当mOffsetPx为0时会被调用,mOffsetPx为0表示当前ViewPager2根本未滑动。

(2). onScrolled方法

在分析这个方法之前,我们看一下这个方法的代码:

public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {

mScrollHappened = true;

// 更新相关值

updateScrollEventValues();

if (mDispatchSelected) {

// 拖动手势释放,ViewPager2正在滑动到正确的位置

mDispatchSelected = false;

boolean scrollingForward = dy > 0 || (dy == 0 && dx < 0 == isLayoutRTL());

mTarget = scrollingForward && mScrollValues.mOffsetPx != 0

? mScrollValues.mPosition + 1 : mScrollValues.mPosition;

if (mDragStartPosition != mTarget) {

dispatchSelected(mTarget);

}

} else if (mAdapterState == STATE_IDLE) {

// 调用了setAdapter方法

dispatchSelected(mScrollValues.mPosition);

}

dispatchScrolled(mScrollValues.mPosition, mScrollValues.mOffset, mScrollValues.mOffsetPx);

// 因为调用了setCurrentItem(x, false)不会触发IDLE状态的产生,所以需要在这里

// 调用dispatchStateChanged方法

if ((mScrollValues.mPosition == mTarget || mTarget == NO_POSITION)

&& mScrollValues.mOffsetPx == 0 && !(mScrollState == SCROLL_STATE_DRAGGING)) {

dispatchStateChanged(SCROLL_STATE_IDLE);

resetState();

}

}

onScrolled方法里面主要做了两件事:

  1. 调用updateScrollEventValues方法更新ScrollEventValues里面的值。
  1. 调用相关方法,更新状态。

关于更新ScrollEventValues里面的值,具体的细节是非常的简单,这里就不解释了。我简单的解释一下几个属性的含义:

| 名称 | 含义 |

| — | — |

| mPosition | 从开始滑动到滑动结束,一直记录着当前滑动到的位置。 |

| mOffset | 从一个页面滑动到另一个页面,记录着滑动的百分比。 |

| mOffsetPx | 记录着从开始滑动的页面与当前状态的滑动。每次滑动结束之后,会被重置。 |

其实总的来说,ScrollEventAdapter的源码是非常简单,这里稍微复杂的就是各种状态的更新和相关的方法的回调。我来简单的总结一下:

  1. 当调用ViewPager2setAdapter方法时,此时应该回调一次dispatchSelected方法。
  1. 当调用setCurrentItem(x, false)方法,不会调用onScrollStateChanged方法,因而不会产生idle状态,因此,我们需要在onScrolled方法特殊处理(onScrolled方法会被调用)。
  1. 正常的拖动和释放,就是onScrollStateChanged方法和onScrolled方法的正常回调。

6. PageTransformerAdapter

=====================================================================================

PageTransformerAdapter的作用将OnPageChangeCallback的事件转换成为一种特殊的事件,什么特殊的事件呢?我以一个例子来解释一下:

  1. 假设ViewPager2此时从A页面滑动到B页面,并且是从右往左滑动,其中A页面的变化范围:[0,-1);B页面的变化范围:[1,0)。
  1. 假设ViewPager2此时从B页面滑动到A页面,并且是从左往右滑动,其中A页面的变化范围:[-1,0);B页面的变化范围:[0,1)。

熟悉ViewPager的同学应该都知道,在ViewPager中也有这么一个东西。这里我们来看一下PageTransformerAdapter是怎么进行转换的。

PageTransformerAdapter实现于OnPageChangeCallback接口,监听的是ScrollEventAdapter的页面滑动事件,然后将页面滑动事件转换成为上面特殊的事件,我们来看看具体的实现,真正的实现在onPageScrolled方法里面:

@Override

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

if (mPageTransformer == null) {

return;

}

float transformOffset = -positionOffset;

for (int i = 0; i < mLayoutManager.getChildCount(); i++) {

View view = mLayoutManager.getChildAt(i);

if (view == null) {

throw new IllegalStateException(String.format(Locale.US,

“LayoutManager returned a null child at pos %d/%d while transforming pages”,

i, mLayoutManager.getChildCount()));

}

int currPos = mLayoutManager.getPosition(view);

float viewOffset = transformOffset + (currPos - position);

mPageTransformer.transformPage(view, viewOffset);

}

}

相信不用我解释上面的代码吧,大家应该都能看懂是怎么实现的。

7. FragmentStateAdapter

===================================================================================

接下来,我们将分析FragmentStateAdapter,看看它是加载Fragment的。在正式分析源码之前,我们先来几个成员变量。

| 变量名称 | 变量类型 | 含义 |

| — | — | — |

| mFragments | LongSparseArray | key为itemId,value为Fragment。表示position与所放Fragment的对应关系(itemId与position有对应关系) |

| mSavedStates | LongSparseArray<Fragment.SavedState> | key为itemId,value为Fragment的状态 |

| mItemIdToViewHolder | LongSparseArray | key为itemId, value为ItemView的id。 |

接下来,我们将分析在Adapter中比较重要的几个方法:

  1. onCreateViewHolder
  1. onBindViewHolder
  1. onViewAttachedToWindow
  1. onViewRecycled
  1. onFailedToRecycleView

如上5个方法都与Fragment加载息息相关,我们一个一个的来看。

(1). onCreateViewHolder方法

onCreateViewHolder方法主要创建ViewHolder,我们来简单看看怎么创建ViewHolder

@NonNull

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

作者2013年从java开发,转做Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

参与过不少面试,也当面试官 面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我整理了一份阿里P7级别的最系统的Android开发主流技术,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你想深入系统学习Android开发,成为一名合格的高级工程师,可以收藏一下这些Android进阶技术选型

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

高级UI与自定义view;
自定义view,Android开发的基本功。

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

NDK开发;
未来的方向,高薪必会。

前沿技术;
组件化,热升级,热修复,框架设计

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
g-tZ7lnalY-1712814616663)]

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

[外链图片转存中…(img-qALtwWx2-1712814616663)]

高级UI与自定义view;
自定义view,Android开发的基本功。

[外链图片转存中…(img-TnxHCSts-1712814616664)]

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

[外链图片转存中…(img-s7cRwdgG-1712814616664)]

NDK开发;
未来的方向,高薪必会。

[外链图片转存中…(img-DVSHKnr9-1712814616664)]

前沿技术;
组件化,热升级,热修复,框架设计

[外链图片转存中…(img-1z4rrxuL-1712814616664)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-9nd4LQsQ-1712814616664)]

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ViewPager和ViewPager2都是Android中的视图控件,用于实现滑动切换不同页面的功能。 ViewPager是Android SDK中的一个类,它可以在同一个Activity中展示多个Fragment,通过左右滑动来切换不同的Fragment。ViewPager可以实现无限循环滑动,但是它的性能不够好,存在一些问题,比如在嵌套使用时会出现滑动冲突等。 ViewPager2ViewPager的升级版,它是在AndroidX库中的一个类,它解决了ViewPager存在的一些问题,比如滑动冲突、性能问题等。ViewPager2支持嵌套滑动,可以实现更加灵活的布局,同时还支持横向和纵向滑动。因此,ViewPager2是更加推荐使用的视图控件。 ### 回答2: ViewPager 和 ViewPager2 都是 Android 平台上的视图容器,它们都用于实现左右滑动切换多个视图的效果。不过,它们也有一些不同的特点。 ViewPager 是 Android 系统自带的视图容器,它主要用于在同一个 Activity 中切换多个 Fragment。ViewPager 会将多个 Fragment 放置在同一个视图中,通过滑动切换 Fragment 来实现左右滑动的效果。ViewPager 比较易用、稳定,使用起来也比较简单,但是在一些功能上有一定的局限性。 ViewPager2ViewPager 的升级版,它是在 AndroidX 中新增加的一个控件。相较于 ViewPager,ViewPager2 有一些更加高级和灵活的功能。首先,ViewPager2 支持 RecyclerView.Adapter,这样用户可以通过 RecyclerView.Adapter 来实现 ViewPager2 中的数据管理,这大大提高了数据操作的灵活性。其次,ViewPager2 支持垂直滑动的效果,这使得用户可以通过上下滑动切换多个视图。此外,ViewPager2 还支持滑块(PageTransformer)和视图预加载(OffscreenPageLimit)等高级功能,让用户可以更加方便地自定义 ViewPager2 的效果和行为。 总的来说,如果只是想要简单实现左右滑动切换多个 Fragment 的效果,可以使用 ViewPager。如果需要更加高级、灵活的功能,或者需要在 ViewPager 中嵌套 RecyclerView 或其他视图控件,则可以选择 ViewPager2。同时,最好在使用 ViewPager2 时,将所有 Fragment 替换为 RecyclerView,这样能够充分利用 ViewPager2 的强大功能。 ### 回答3: ViewPager和ViewPager2是Android平台上常用的 View容器 组件。它们最主要的作用是管理多个子view的滑动显示,类似于滑动的页面。 ViewPager从Android API Level 11就被引入,它支持从左往右滑动查看多个子视图,以轻松实现流畅的“屏幕滑动”效果,常见的使用场景包括相册、图库、图片轮播图等。在使用ViewPager时,开发者需要自己实现适配器,根据需要返回子View。且ViewPager中每个页面的宽度是相等的,无法进行自由的布局。 而ViewPager2是新增的一个组件,它是AndroidX中的一部分,于2019发布。ViewPager2相对于ViewPager的最大改进就在于支持不同宽度的页面。除了滑动方向以外,ViewPager2还支持从RecyclerView中使用适配器,从而不仅仅可以使用View,还可以使用任何RecyclerView的特性和布局(如GridLayoutManager等)。另一个重要的改进是支持了多层嵌套,并且同步了更多的触摸事件,增强了原生的滑动手势支持。 总之,ViewPager2ViewPager的升级版,它具有更多灵活的布局和更好的性能。开发者可以根据自己的需求选择使用ViewPager或ViewPager2,相信在未来的Android开发中,ViewPager2会成为首选。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值