ViewPager类源码详解

getItemPosition()判断一项的位置是否改变(如果单项的视图需要改变,必须重写此函数,否则数据源的改变不会反映到Viewpager中)

 

此处以support-compat-27.1.1为标准进行源码分析

ViewPager类是单纯作为适配器模式的View存在,拥有适配器模式的View的一般原则,将View的添加与删除交给适配器进行,需要显示的Item的个数与数据源全部由适配器进行控制。

一下进行内部类的分析:

  1. static class ItemInfo ViewPager类的item包含item状态与持有的额外数据
    1. object:Object 可持有的object,

赋值:由PagerAdapter的instantiateItem()返回值进行赋值

使用:持有对应于Item的额外数据,作为检查item位置是否改变,检查Item的视图与object是否对应

  • PageAdapter.getItemPosition()的参数
  • PageAdapter.destroyItem()的参数
  • PageAdapter.isViewFromObject()的参数
  • PageAdapter.setPrimaryItem()的参数
    1. position:int item对应的索引
    2. scrolling:boolean 是否正在滑动
    3. widthFactor:float 宽度百分比
    4. offset:float 偏移量
  • public interface OnPageChangeListener 所选界面的更改状态
    1. void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 当界面滑动时触发
      1. 第一个参数为当前item索引,滑动结束后会改变
      2. 第二个参数为数值在[0,1)的偏移量
      3. 第三个参数为单位为pixels的偏移量
    2. void onPageSelected(int position) 当前界面改变时触发,切换界面的动画不一定结束
      1. 参数为新的item的索引
    3. void onPageScrollStateChanged(int state) 当滑动状态发生改变时触发
      1. 有三个值,SCROLL_STATE_IDLE 表示滑动停止,处于空闲状态,SCROLL_STATE_DRAGGING 表示开始拖动,SCROLL_STATE_SETTLING 表示开始设置拖动
  • public static class SimpleOnPageChangeListener implements onPageScrollStateChanged继承自OnPageChangeListener的内部静态类,如果不需要实现所有的OnPageChangeListener的方法可以继承此类,之后重写需要的函数
  • public interface PageTransformer 当item滑动时会触发此接口的函数
    1. void transformPage(View page, float position); 可与此函数中改变item的视图
      1. 第一个参数为要改变的item的视图
      2. 第二个参数为表示第一个参数是哪个item,0表示中间的item视图,-1表示左边的item视图,1表示右边的item视图
  • public interface OnAdapterChangeListener 当adapter改变时会触发
    1. void onAdapterChanged(@NonNull ViewPager viewPager,@Nullable PagerAdapter oldAdapter,@Nullable PagerAdapter newAdapter) 当ViewPager的setAdapter()被调用时触发此函数
      1. 第一个参数为当前ViewPager
      2. 第二个参数为之前的PagerAdapter
      3. 第三个参数为新的PagerAdapter
  • public @interface DecorView 注解,在ViewParams中的LayoutParams使用,判断是否是ViewPager的修饰的标志
  • public static class SavedState extends AbsSavedState 继承自AbsSavedState实现了Parcelable,用于序列化保存状态
    1. position:int 当前索引
    2. adapterState:Parcelable adapter的保存数据
    3. loader:ClassLoader class加载工具类

函数没什么可说的,都是序列化保存状态的一般函数,不会的自行查询官方文档

  1. class MyAccessibilityDelegate extends AccessibilityDelegateCompat 辅助功能,实现了一些代理的函数,因为本人对代理并不是特别明白,所以在此就不班门弄斧了,有兴趣的小伙伴可以自行查询官方文档
  2. private class PagerObserver extends DataSetObserver PagerAdapter的notifyDataSetChanged()函数被调用时会触发此类中的函数,执行ViewPager的dataSetChanged()函数进行数据的更新,一般用于数据源变化时通知PagerAdapter与ViewPager进行变化
  3. LayoutParams几乎每一个google提供的View中都会存在的元素,布局参数
    1. isDecor 是否是ViewPager的修饰类,目前原生只有PagerTitleStrip和TabLayout是ViewPager的修饰
    2. gravity 不用说
    3. widthFactor 宽度的百分比,值域 0-1
    4. needsMeasure 需要在确定位置之前进行计算的话为true,非必需使用,不建议更改
    5. position 索引
    6. childIndex 第几个进行渲染,isDecor为true会比isDecor为false后渲染
  4. static class ViewPositionComparator implements Comparator<View> ViewPager的子view渲染顺序的比较器,没什么好说的

至此,内部类分析完毕,下面继续属性的分析:

  1. private static final String TAG = "ViewPager" TAG
  2. private static final boolean DEBUG = false 测试使用
  3. private static final boolean USE_CACHE = false 是否使用缓存渲染模式,使用缓存渲染模式,会加快渲染速度,但是会占用有定的内存
  4. private static final int DEFAULT_OFFSCREEN_PAGES = 1 默认的缓存渲染item数量
  5. private static final int MAX_SETTLE_DURATION = 600 允许的最大的滑动时间,单位ms
  6. private static final int MIN_DISTANCE_FOR_FLING = 25 移动的最小距离,单位dips
  7. private static final int DEFAULT_GUTTER_SIZE = 16 默认的触动滑动的最小距离,单位dips
  8. private static final int MIN_FLING_VELOCITY = 400 允许的最小滑动速度,单位dips
  9. static final int[] LAYOUT_ATTRS = new int[] { android.R.attr.layout_gravity}; LayoutParams的两个参的构造方法会使用获取布局参数中gravity的值
  10. private int mExpectedAdapterCount item的数量,不能更改,更改就会报错
  11. private static final Comparator<ItemInfo> COMPARATOR 将ItemInfo按position排序
  12. private static final Interpolator sInterpolator 时间插值类,很多人估计都没有接触过,作用是能控制目标的变化值进行对于的改变,主要使用于动画中
  13. private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>() item的集合
  14. private final ItemInfo mTempItem = new ItemInfo() 作为数据源改变后更新item的临时item存在
  15. private final Rect mTempRect = new Rect() 作为临时Rect存在
  16. PagerAdapter mAdapter 不用说
  17. int mCurItem 当前正在显示的page的索引
  18. private int mRestoredCurItem = -1 执行数据保存后恢复时的page的索引
  19. private Parcelable mRestoredAdapterState = null 执行数据保存后恢复时的adapter所保存的数据,用于adapter的数据恢复
  20. private ClassLoader mRestoredClassLoader = null 执行数据恢复时的ClassLoader
  21. private Scroller mScroller 滑动辅助类,用于计算插值
  22. private boolean mIsScrollStarted 是否开始滑动
  23. private PagerObserver mObserver 传入adapter的观察者,用于观察数据改变
  24. private int mPageMargin page之间的边缘距离
  25. private Drawable mMarginDrawable page之间的图片填充
  26. private int mTopPageBounds page的上边界
  27. private int mBottomPageBounds page的下边界
  28. private float mFirstOffset = -Float.MAX_VALUE 第一个item的偏移量
  29. private float mLastOffset = Float.MAX_VALUE 最后一个item的偏移量
  30. private int mChildWidthMeasureSpec 子控件宽的measureSpec,不知道measureSpec是什么请深思己过
  31. private int mChildHeightMeasureSpec 子控件高的measureSpec,不知道measureSpec是什么请深思己过
  32. private boolean mInLayout 是否正在计算布局
  33. private boolean mScrollingCacheEnabled 是否使用缓存模式进行渲染
  34. private boolean mPopulatePending 是否等待填充
  35. private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES 缓存渲染item数量
  36. private boolean mIsBeingDragged 是否正在被拖动
  37. private boolean mIsUnableToDrag 是否不能进行拖动
  38. private int mDefaultGutterSize 默认触动滑动的距离,单位dips
  39. private int mGutterSize 触动滑动的距离,单位dips
  40. private int mTouchSlop 触发滑动的最小距离
  41. private float mLastMotionX 最后触摸的X轴相对坐标
  42. private float mLastMotionY 最后触摸的Y轴相对坐标
  43. private float mInitialMotionX 触摸时的X轴的相对坐标
  44. private float mInitialMotionY 触摸时的Y轴的相对坐标
  45. private int mActivePointerId = INVALID_POINTER 指针的ID,用来判断多指针时的指针一致性
  46. private static final int INVALID_POINTER = -1 指针的初始化值
  47. private VelocityTracker mVelocityTracker 滑动速度检测辅助类
  48. private int mMinimumVelocity 最小的滑动速度,单位为ms
  49. private int mMaximumVelocity 最大的滑动速度,单位为ms
  50. private int mFlingDistance 滑动的最小距离,单位dips
  51. private int mCloseEnough 不懂
  52. private static final int CLOSE_ENOUGH = 2 同上
  53. private boolean mFakeDragging 字面意思,假滑动?没看到使用的地方,估计是google的人员开发测试使用
  54. private long mFakeDragBeginTime 假滑动的滑动时间,没有使用
  55. private EdgeEffect mLeftEdge 左边缘效果类
  56. private EdgeEffect mRightEdge 右边缘效果
  57. private boolean mFirstLayout = true 是否是第一次布局,添加入window算是第一次布局,重新设置adapter也算是第一次布局
  58. private boolean mNeedCalculatePageOffsets = false 页面是否需要计算偏移量,没有用,应该是google人员测试时使用
  59. private boolean mCalledSuper 字面意思为,访问super,但是使用的时候是在onPageScrolled方法执行之前置为false,onPageScrolled执行之后置为true,如果onPageScrolled执行完成后仍为false(onPageScrolled未执行到最后,执行过程中出现错误)则抛出异常
  60. private int mDecorChildCount decor级别的自视图总数
  61. private List<OnPageChangeListener> mOnPageChangeListeners 持有所有OnPageChangeListener的集合
  62. OnPageChangeListener mOnPageChangeListener OnPageChangeListener回调,会在mOnPageChangeListeners持有的所有回调执行之前执行
  63. private OnPageChangeListener mInternalPageChangeListener OnPageChangeListener回调,会在mOnPageChangeListeners持有的所有回调执行之后执行
  64. private List<OnAdapterChangeListener> mAdapterChangeListeners 持有所有的OnAdapterChangeListener的集合,会在执行setAdapter方法之后执行回调
  65. private PageTransformer mPageTransformer 持有的页面变化器,可以用其实现页面切换时的状态回调与状态变化
  66. private int mPageTransformerLayerType 页面变化器的级别,启动硬件加速的级别
  67. private static final int DRAW_ORDER_DEFAULT = 0 默认绘制规则,不需要排序
  68. private static final int DRAW_ORDER_FORWARD = 1 绘制规则,正序排序
  69. private static final int DRAW_ORDER_REVERSE = 2 绘制规则,倒序排序
  70. private int mDrawingOrder 持有的当前的绘制规则
  71. private ArrayList<View> mDrawingOrderedChildren 持有的排好序的子view集合
  72. private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator() 排序所需的比较器
  73. public static final int SCROLL_STATE_IDLE = 0 滑动状态,滑动停止,处于空闲状
  74. public static final int SCROLL_STATE_DRAGGING = 1 滑动状态,开始拖动
  75. public static final int SCROLL_STATE_SETTLING = 2 滑动状态,开始设置
  76. private final Runnable mEndScrollRunnable = new Runnable() {

@Override

public void run(){

setScrollState(SCROLL_STATE_IDLE);

populate();

}

} Runnable,拖动结束后,设置空闲状态,并进行当前页绘制

  1. private int mScrollState = SCROLL_STATE_IDLE 当前滑动状态

至此,内部类与属性分析结束,下面开始方法的分析:

  1. public ViewPager(@NonNull Context context) 构造方法
  2. public ViewPager(@NonNull Context context, @Nullable AttributeSet attrs) 构造方法,构造方法最后都是调用到初始化方法initViewPager()
  3. void initViewPager() 初始化,代码自行去研究,此处不做太深的讲解
  4. protected void onDetachedFromWindow() 从window中移除时的方法
  5. void setScrollState(int newState) 设置滑动状态
  6. public void setAdapter(@Nullable PagerAdapter adapter) 设置adapter
  7. private void removeNonDecorViews() 移除除装饰性View之外的所有View
  8. public PagerAdapter getAdapter() 获取持有的adapter
  9. public void addOnAdapterChangeListener(@NonNull OnAdapterChangeListener listener) 添加adapter发生变化的监听
  10. public void removeOnAdapterChangeListener(@NonNull OnAdapterChangeListener listener) 移除adapter发生变化的监听
  11. private int getClientWidth() 获取可以进行绘制的宽度
  12. public void setCurrentItem(int item) 设置当前选中的item
  13. public void setCurrentItem(int item, boolean smoothScroll) 设置当前选中的item
  14. public int getCurrentItem() 获取当前选中的item
  15. void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) 执行item选中的方法
  16. void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) 真正执行item选中的方法,第一个参数为要选中的item,第二个参数为是否是由顺滑滑动,第三个参数为是否是永久的,第四个参数为滑动速度
  17. private void scrollToItem(int item, boolean smoothScroll, int velocity, boolean dispatchSelected) 滑动到某一个item
  18. public void setOnPageChangeListener(OnPageChangeListener listener) 设置page状态监听,已过时方法
  19. public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) 添加page状态监听
  20. public void removeOnPageChangeListener(@NonNull OnPageChangeListener listener) 移除page状态监听
  21. public void clearOnPageChangeListeners() 清空page状态监听
  22. public void setPageTransformer(boolean reverseDrawingOrder, @Nullable PageTransformer transformer) 设置page变化时的变化器
  23. public void setPageTransformer(boolean reverseDrawingOrder, @Nullable PageTransformer transformer, int pageLayerType) 真正设置page变化时的变化器
  24. protected int getChildDrawingOrder(int childCount, int i) 返回绘制子类迭代索引
  25. OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) 设置内部的page改变监听
  26. public int getOffscreenPageLimit() 获取缓存的page数量限制
  27. public void setOffscreenPageLimit(int limit) 设置缓存的page数量限制
  28. public void setPageMargin(int marginPixels) 设置page之间的边缘距离
  29. public int getPageMargin() 获取page之间的边缘距离
  30. public void setPageMarginDrawable(@Nullable Drawable d) 设置page边缘的填充drawable
  31. public void setPageMarginDrawable(@DrawableRes int resId) 设置page边缘的填充drawable
  32. protected boolean verifyDrawable(Drawable who) 验证drawable
  33. protected void drawableStateChanged() 视图状态发生变化触发的方法,触发视图触摸状态的方法
  34. distanceInfluenceForSnapDuration(float f) 时间与距离的装换方法,使动画时长受到屏幕移动距离的影响,
  35. void smoothScrollTo(int x, int y) 类似scrollBy,但是是更为流畅的滚动
  36. void smoothScrollTo(int x, int y, int velocity) 类似scrollBy,但是是更为流畅的滚动,真正的实现方法
  37. ItemInfo addNewItem(int position, int index) 添加新的item
  38. void dataSetChanged() 随数据源变化
  39. void populate() 确定选中项进行绘制
  40. void populate(int newCurrentItem) 真正的确定选中项后进行绘制
  41. private void sortChildDrawingOrder() 子view视图绘制排序
  42. private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCurInfo) 计算页面偏移量
  43. public Parcelable onSaveInstanceState() 保存状态
  44. public void onRestoreInstanceState(Parcelable state) 恢复状态
  45. public void addView(View child, int index, ViewGroup.LayoutParams params) 添加子view
  46. private static boolean isDecorView(@NonNull View view) 是否是装饰类
  47. public void removeView(View view) 移除子view
  48. ItemInfo infoForChild(View child) 根据子view校验与返回iteminfo
  49. ItemInfo infoForAnyChild(View child) 根据子view校验返回iteminfo
  50. ItemInfo infoForPosition(int position) 根据position校验返回iteminfo
  51. protected void onAttachedToWindow() 被添加到window,并可进行界面操作
  52. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 视图计算
  53. protected void onSizeChanged(int w, int h, int oldw, int oldh) 视图大小发生改变
  54. private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) 重新计算滚动位置
  55. protected void onLayout(boolean changed, int l, int t, int r, int b) 视图布局
  56. public void computeScroll() 计算滚动
  57. private boolean pageScrolled(int xpos) page滚动
  58. protected void onPageScrolled(int position, float offset, int offsetPixels) 当page滚动时调用的方法
  59. private void dispatchOnPageScrolled(int position, float offset, int offsetPixels) 分发page滚动时调用的方法
  60. private void dispatchOnPageSelected(int position) 分发page选中时调用的方法
  61. private void dispatchOnScrollStateChanged(int state) 分发滚动状态改变的方法
  62. private void completeScroll(boolean postEvents) 结束滚动的方法
  63. private boolean isGutterDrag(float x, float dx) 是否允许进行拖动
  64. private void enableLayers(boolean enable) 控制是否启用硬件加速的级别
  65. public boolean onInterceptTouchEvent(MotionEvent ev) 分发触摸事件的方法
  66. public boolean onTouchEvent(MotionEvent ev) 触摸事件方法
  67. private boolean resetTouch() 重置触摸
  68. private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) 通知父控件,不要拦截触摸事件
  69. private boolean performDrag(float x) 真正的进行拖动
  70. private ItemInfo infoForCurrentScrollPosition() 获取当前滑动的iteminfo
  71. private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) 确定目标page
  72. public void draw(Canvas canvas) 视图绘制
  73. protected void onDraw(Canvas canvas) 在视图绘制时调用
  74. public boolean beginFakeDrag() 开始假滑动,无用
  75. public void endFakeDrag() 结束假滑动,无用
  76. public void fakeDragBy(float xOffset) 假滑动,无用
  77. public boolean isFakeDragging() 是否是假滑动
  78. private void onSecondaryPointerUp(MotionEvent ev) 二级指针释放
  79. private void endDrag() 结束滑动
  80. private void setScrollingCacheEnabled(boolean enabled) 是否启用滚动缓存模式
  81. public boolean canScrollHorizontally(int direction) 是否可以水平滚动
  82. protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) 是否可以滚动
  83. public boolean dispatchKeyEvent(KeyEvent event) 分发按键事件
  84. public boolean executeKeyEvent(@NonNull KeyEvent event) 执行按键事件
  85. public boolean arrowScroll(int direction) 处理箭头滚动,有FOCUS_LEFT,FOCUS_BACKWARD,FOCUS_RIGHT,FOCUS_FORWARD
  86. private Rect getChildRectInPagerCoordinates(Rect outRect, View child) 获取页导航坐标中的子矩形
  87. boolean pageLeft() 向左翻页,返回boolean,表示翻页是否成功
  88. boolean pageRight() 向右翻页,返回boolean,表示翻页是否成功
  89. public void addFocusables(ArrayList<View> views, int direction, int focusableMode) 添加可聚焦视图,只允许当前界面可聚焦
  90. public void addTouchables(ArrayList<View> views) 添加可触摸视图,只允许当前界面可触摸
  91. protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) 请求焦点的子类,只允许当前界面可调焦
  92. public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) 辅助功能事件的分发
  93. protected ViewGroup.LayoutParams generateDefaultLayoutParams() 生成默认的布局参数
  94. protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) 生成布局参数
  95. protected boolean checkLayoutParams(ViewGroup.LayoutParams p) 检查布局参数
  96. public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) 生成布局参数

至此,ViewPager的类源码大体都分析完了,具体的详细内容需要自行看代码进行理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值