getItemPosition()判断一项的位置是否改变(如果单项的视图需要改变,必须重写此函数,否则数据源的改变不会反映到Viewpager中)
此处以support-compat-27.1.1为标准进行源码分析
ViewPager类是单纯作为适配器模式的View存在,拥有适配器模式的View的一般原则,将View的添加与删除交给适配器进行,需要显示的Item的个数与数据源全部由适配器进行控制。
一下进行内部类的分析:
- static class ItemInfo ViewPager类的item包含item状态与持有的额外数据
- object:Object 可持有的object,
赋值:由PagerAdapter的instantiateItem()返回值进行赋值
使用:持有对应于Item的额外数据,作为检查item位置是否改变,检查Item的视图与object是否对应
- PageAdapter.getItemPosition()的参数
- PageAdapter.destroyItem()的参数
- PageAdapter.isViewFromObject()的参数
- PageAdapter.setPrimaryItem()的参数
-
- position:int item对应的索引
- scrolling:boolean 是否正在滑动
- widthFactor:float 宽度百分比
- offset:float 偏移量
- public interface OnPageChangeListener 所选界面的更改状态
- void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 当界面滑动时触发
- 第一个参数为当前item索引,滑动结束后会改变
- 第二个参数为数值在[0,1)的偏移量
- 第三个参数为单位为pixels的偏移量
- void onPageSelected(int position) 当前界面改变时触发,切换界面的动画不一定结束
- 参数为新的item的索引
- void onPageScrollStateChanged(int state) 当滑动状态发生改变时触发
- 有三个值,SCROLL_STATE_IDLE 表示滑动停止,处于空闲状态,SCROLL_STATE_DRAGGING 表示开始拖动,SCROLL_STATE_SETTLING 表示开始设置拖动
- void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 当界面滑动时触发
- public static class SimpleOnPageChangeListener implements onPageScrollStateChanged继承自OnPageChangeListener的内部静态类,如果不需要实现所有的OnPageChangeListener的方法可以继承此类,之后重写需要的函数
- public interface PageTransformer 当item滑动时会触发此接口的函数
- void transformPage(View page, float position); 可与此函数中改变item的视图
- 第一个参数为要改变的item的视图
- 第二个参数为表示第一个参数是哪个item,0表示中间的item视图,-1表示左边的item视图,1表示右边的item视图
- void transformPage(View page, float position); 可与此函数中改变item的视图
- public interface OnAdapterChangeListener 当adapter改变时会触发
- void onAdapterChanged(@NonNull ViewPager viewPager,@Nullable PagerAdapter oldAdapter,@Nullable PagerAdapter newAdapter) 当ViewPager的setAdapter()被调用时触发此函数
- 第一个参数为当前ViewPager
- 第二个参数为之前的PagerAdapter
- 第三个参数为新的PagerAdapter
- void onAdapterChanged(@NonNull ViewPager viewPager,@Nullable PagerAdapter oldAdapter,@Nullable PagerAdapter newAdapter) 当ViewPager的setAdapter()被调用时触发此函数
- public @interface DecorView 注解,在ViewParams中的LayoutParams使用,判断是否是ViewPager的修饰的标志
- public static class SavedState extends AbsSavedState 继承自AbsSavedState实现了Parcelable,用于序列化保存状态
- position:int 当前索引
- adapterState:Parcelable adapter的保存数据
- loader:ClassLoader class加载工具类
函数没什么可说的,都是序列化保存状态的一般函数,不会的自行查询官方文档
- class MyAccessibilityDelegate extends AccessibilityDelegateCompat 辅助功能,实现了一些代理的函数,因为本人对代理并不是特别明白,所以在此就不班门弄斧了,有兴趣的小伙伴可以自行查询官方文档
- private class PagerObserver extends DataSetObserver PagerAdapter的notifyDataSetChanged()函数被调用时会触发此类中的函数,执行ViewPager的dataSetChanged()函数进行数据的更新,一般用于数据源变化时通知PagerAdapter与ViewPager进行变化
- LayoutParams几乎每一个google提供的View中都会存在的元素,布局参数
- isDecor 是否是ViewPager的修饰类,目前原生只有PagerTitleStrip和TabLayout是ViewPager的修饰
- gravity 不用说
- widthFactor 宽度的百分比,值域 0-1
- needsMeasure 需要在确定位置之前进行计算的话为true,非必需使用,不建议更改
- position 索引
- childIndex 第几个进行渲染,isDecor为true会比isDecor为false后渲染
- static class ViewPositionComparator implements Comparator<View> ViewPager的子view渲染顺序的比较器,没什么好说的
至此,内部类分析完毕,下面继续属性的分析:
- private static final String TAG = "ViewPager" TAG
- private static final boolean DEBUG = false 测试使用
- private static final boolean USE_CACHE = false 是否使用缓存渲染模式,使用缓存渲染模式,会加快渲染速度,但是会占用有定的内存
- private static final int DEFAULT_OFFSCREEN_PAGES = 1 默认的缓存渲染item数量
- private static final int MAX_SETTLE_DURATION = 600 允许的最大的滑动时间,单位ms
- private static final int MIN_DISTANCE_FOR_FLING = 25 移动的最小距离,单位dips
- private static final int DEFAULT_GUTTER_SIZE = 16 默认的触动滑动的最小距离,单位dips
- private static final int MIN_FLING_VELOCITY = 400 允许的最小滑动速度,单位dips
- static final int[] LAYOUT_ATTRS = new int[] { android.R.attr.layout_gravity}; LayoutParams的两个参的构造方法会使用获取布局参数中gravity的值
- private int mExpectedAdapterCount item的数量,不能更改,更改就会报错
- private static final Comparator<ItemInfo> COMPARATOR 将ItemInfo按position排序
- private static final Interpolator sInterpolator 时间插值类,很多人估计都没有接触过,作用是能控制目标的变化值进行对于的改变,主要使用于动画中
- private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>() item的集合
- private final ItemInfo mTempItem = new ItemInfo() 作为数据源改变后更新item的临时item存在
- private final Rect mTempRect = new Rect() 作为临时Rect存在
- PagerAdapter mAdapter 不用说
- int mCurItem 当前正在显示的page的索引
- private int mRestoredCurItem = -1 执行数据保存后恢复时的page的索引
- private Parcelable mRestoredAdapterState = null 执行数据保存后恢复时的adapter所保存的数据,用于adapter的数据恢复
- private ClassLoader mRestoredClassLoader = null 执行数据恢复时的ClassLoader
- private Scroller mScroller 滑动辅助类,用于计算插值
- private boolean mIsScrollStarted 是否开始滑动
- private PagerObserver mObserver 传入adapter的观察者,用于观察数据改变
- private int mPageMargin page之间的边缘距离
- private Drawable mMarginDrawable page之间的图片填充
- private int mTopPageBounds page的上边界
- private int mBottomPageBounds page的下边界
- private float mFirstOffset = -Float.MAX_VALUE 第一个item的偏移量
- private float mLastOffset = Float.MAX_VALUE 最后一个item的偏移量
- private int mChildWidthMeasureSpec 子控件宽的measureSpec,不知道measureSpec是什么请深思己过
- private int mChildHeightMeasureSpec 子控件高的measureSpec,不知道measureSpec是什么请深思己过
- private boolean mInLayout 是否正在计算布局
- private boolean mScrollingCacheEnabled 是否使用缓存模式进行渲染
- private boolean mPopulatePending 是否等待填充
- private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES 缓存渲染item数量
- private boolean mIsBeingDragged 是否正在被拖动
- private boolean mIsUnableToDrag 是否不能进行拖动
- private int mDefaultGutterSize 默认触动滑动的距离,单位dips
- private int mGutterSize 触动滑动的距离,单位dips
- private int mTouchSlop 触发滑动的最小距离
- private float mLastMotionX 最后触摸的X轴相对坐标
- private float mLastMotionY 最后触摸的Y轴相对坐标
- private float mInitialMotionX 触摸时的X轴的相对坐标
- private float mInitialMotionY 触摸时的Y轴的相对坐标
- private int mActivePointerId = INVALID_POINTER 指针的ID,用来判断多指针时的指针一致性
- private static final int INVALID_POINTER = -1 指针的初始化值
- private VelocityTracker mVelocityTracker 滑动速度检测辅助类
- private int mMinimumVelocity 最小的滑动速度,单位为ms
- private int mMaximumVelocity 最大的滑动速度,单位为ms
- private int mFlingDistance 滑动的最小距离,单位dips
- private int mCloseEnough 不懂
- private static final int CLOSE_ENOUGH = 2 同上
- private boolean mFakeDragging 字面意思,假滑动?没看到使用的地方,估计是google的人员开发测试使用
- private long mFakeDragBeginTime 假滑动的滑动时间,没有使用
- private EdgeEffect mLeftEdge 左边缘效果类
- private EdgeEffect mRightEdge 右边缘效果
- private boolean mFirstLayout = true 是否是第一次布局,添加入window算是第一次布局,重新设置adapter也算是第一次布局
- private boolean mNeedCalculatePageOffsets = false 页面是否需要计算偏移量,没有用,应该是google人员测试时使用
- private boolean mCalledSuper 字面意思为,访问super,但是使用的时候是在onPageScrolled方法执行之前置为false,onPageScrolled执行之后置为true,如果onPageScrolled执行完成后仍为false(onPageScrolled未执行到最后,执行过程中出现错误)则抛出异常
- private int mDecorChildCount decor级别的自视图总数
- private List<OnPageChangeListener> mOnPageChangeListeners 持有所有OnPageChangeListener的集合
- OnPageChangeListener mOnPageChangeListener OnPageChangeListener回调,会在mOnPageChangeListeners持有的所有回调执行之前执行
- private OnPageChangeListener mInternalPageChangeListener OnPageChangeListener回调,会在mOnPageChangeListeners持有的所有回调执行之后执行
- private List<OnAdapterChangeListener> mAdapterChangeListeners 持有所有的OnAdapterChangeListener的集合,会在执行setAdapter方法之后执行回调
- private PageTransformer mPageTransformer 持有的页面变化器,可以用其实现页面切换时的状态回调与状态变化
- private int mPageTransformerLayerType 页面变化器的级别,启动硬件加速的级别
- private static final int DRAW_ORDER_DEFAULT = 0 默认绘制规则,不需要排序
- private static final int DRAW_ORDER_FORWARD = 1 绘制规则,正序排序
- private static final int DRAW_ORDER_REVERSE = 2 绘制规则,倒序排序
- private int mDrawingOrder 持有的当前的绘制规则
- private ArrayList<View> mDrawingOrderedChildren 持有的排好序的子view集合
- private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator() 排序所需的比较器
- public static final int SCROLL_STATE_IDLE = 0 滑动状态,滑动停止,处于空闲状
- public static final int SCROLL_STATE_DRAGGING = 1 滑动状态,开始拖动
- public static final int SCROLL_STATE_SETTLING = 2 滑动状态,开始设置
- private final Runnable mEndScrollRunnable = new Runnable() {
@Override
public void run(){
setScrollState(SCROLL_STATE_IDLE);
populate();
}
} Runnable,拖动结束后,设置空闲状态,并进行当前页绘制
- private int mScrollState = SCROLL_STATE_IDLE 当前滑动状态
至此,内部类与属性分析结束,下面开始方法的分析:
- public ViewPager(@NonNull Context context) 构造方法
- public ViewPager(@NonNull Context context, @Nullable AttributeSet attrs) 构造方法,构造方法最后都是调用到初始化方法initViewPager()
- void initViewPager() 初始化,代码自行去研究,此处不做太深的讲解
- protected void onDetachedFromWindow() 从window中移除时的方法
- void setScrollState(int newState) 设置滑动状态
- public void setAdapter(@Nullable PagerAdapter adapter) 设置adapter
- private void removeNonDecorViews() 移除除装饰性View之外的所有View
- public PagerAdapter getAdapter() 获取持有的adapter
- public void addOnAdapterChangeListener(@NonNull OnAdapterChangeListener listener) 添加adapter发生变化的监听
- public void removeOnAdapterChangeListener(@NonNull OnAdapterChangeListener listener) 移除adapter发生变化的监听
- private int getClientWidth() 获取可以进行绘制的宽度
- public void setCurrentItem(int item) 设置当前选中的item
- public void setCurrentItem(int item, boolean smoothScroll) 设置当前选中的item
- public int getCurrentItem() 获取当前选中的item
- void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) 执行item选中的方法
- void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) 真正执行item选中的方法,第一个参数为要选中的item,第二个参数为是否是由顺滑滑动,第三个参数为是否是永久的,第四个参数为滑动速度
- private void scrollToItem(int item, boolean smoothScroll, int velocity, boolean dispatchSelected) 滑动到某一个item
- public void setOnPageChangeListener(OnPageChangeListener listener) 设置page状态监听,已过时方法
- public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) 添加page状态监听
- public void removeOnPageChangeListener(@NonNull OnPageChangeListener listener) 移除page状态监听
- public void clearOnPageChangeListeners() 清空page状态监听
- public void setPageTransformer(boolean reverseDrawingOrder, @Nullable PageTransformer transformer) 设置page变化时的变化器
- public void setPageTransformer(boolean reverseDrawingOrder, @Nullable PageTransformer transformer, int pageLayerType) 真正设置page变化时的变化器
- protected int getChildDrawingOrder(int childCount, int i) 返回绘制子类迭代索引
- OnPageChangeListener setInternalPageChangeListener(OnPageChangeListener listener) 设置内部的page改变监听
- public int getOffscreenPageLimit() 获取缓存的page数量限制
- public void setOffscreenPageLimit(int limit) 设置缓存的page数量限制
- public void setPageMargin(int marginPixels) 设置page之间的边缘距离
- public int getPageMargin() 获取page之间的边缘距离
- public void setPageMarginDrawable(@Nullable Drawable d) 设置page边缘的填充drawable
- public void setPageMarginDrawable(@DrawableRes int resId) 设置page边缘的填充drawable
- protected boolean verifyDrawable(Drawable who) 验证drawable
- protected void drawableStateChanged() 视图状态发生变化触发的方法,触发视图触摸状态的方法
- distanceInfluenceForSnapDuration(float f) 时间与距离的装换方法,使动画时长受到屏幕移动距离的影响,
- void smoothScrollTo(int x, int y) 类似scrollBy,但是是更为流畅的滚动
- void smoothScrollTo(int x, int y, int velocity) 类似scrollBy,但是是更为流畅的滚动,真正的实现方法
- ItemInfo addNewItem(int position, int index) 添加新的item
- void dataSetChanged() 随数据源变化
- void populate() 确定选中项进行绘制
- void populate(int newCurrentItem) 真正的确定选中项后进行绘制
- private void sortChildDrawingOrder() 子view视图绘制排序
- private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCurInfo) 计算页面偏移量
- public Parcelable onSaveInstanceState() 保存状态
- public void onRestoreInstanceState(Parcelable state) 恢复状态
- public void addView(View child, int index, ViewGroup.LayoutParams params) 添加子view
- private static boolean isDecorView(@NonNull View view) 是否是装饰类
- public void removeView(View view) 移除子view
- ItemInfo infoForChild(View child) 根据子view校验与返回iteminfo
- ItemInfo infoForAnyChild(View child) 根据子view校验返回iteminfo
- ItemInfo infoForPosition(int position) 根据position校验返回iteminfo
- protected void onAttachedToWindow() 被添加到window,并可进行界面操作
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 视图计算
- protected void onSizeChanged(int w, int h, int oldw, int oldh) 视图大小发生改变
- private void recomputeScrollPosition(int width, int oldWidth, int margin, int oldMargin) 重新计算滚动位置
- protected void onLayout(boolean changed, int l, int t, int r, int b) 视图布局
- public void computeScroll() 计算滚动
- private boolean pageScrolled(int xpos) page滚动
- protected void onPageScrolled(int position, float offset, int offsetPixels) 当page滚动时调用的方法
- private void dispatchOnPageScrolled(int position, float offset, int offsetPixels) 分发page滚动时调用的方法
- private void dispatchOnPageSelected(int position) 分发page选中时调用的方法
- private void dispatchOnScrollStateChanged(int state) 分发滚动状态改变的方法
- private void completeScroll(boolean postEvents) 结束滚动的方法
- private boolean isGutterDrag(float x, float dx) 是否允许进行拖动
- private void enableLayers(boolean enable) 控制是否启用硬件加速的级别
- public boolean onInterceptTouchEvent(MotionEvent ev) 分发触摸事件的方法
- public boolean onTouchEvent(MotionEvent ev) 触摸事件方法
- private boolean resetTouch() 重置触摸
- private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) 通知父控件,不要拦截触摸事件
- private boolean performDrag(float x) 真正的进行拖动
- private ItemInfo infoForCurrentScrollPosition() 获取当前滑动的iteminfo
- private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) 确定目标page
- public void draw(Canvas canvas) 视图绘制
- protected void onDraw(Canvas canvas) 在视图绘制时调用
- public boolean beginFakeDrag() 开始假滑动,无用
- public void endFakeDrag() 结束假滑动,无用
- public void fakeDragBy(float xOffset) 假滑动,无用
- public boolean isFakeDragging() 是否是假滑动
- private void onSecondaryPointerUp(MotionEvent ev) 二级指针释放
- private void endDrag() 结束滑动
- private void setScrollingCacheEnabled(boolean enabled) 是否启用滚动缓存模式
- public boolean canScrollHorizontally(int direction) 是否可以水平滚动
- protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) 是否可以滚动
- public boolean dispatchKeyEvent(KeyEvent event) 分发按键事件
- public boolean executeKeyEvent(@NonNull KeyEvent event) 执行按键事件
- public boolean arrowScroll(int direction) 处理箭头滚动,有FOCUS_LEFT,FOCUS_BACKWARD,FOCUS_RIGHT,FOCUS_FORWARD
- private Rect getChildRectInPagerCoordinates(Rect outRect, View child) 获取页导航坐标中的子矩形
- boolean pageLeft() 向左翻页,返回boolean,表示翻页是否成功
- boolean pageRight() 向右翻页,返回boolean,表示翻页是否成功
- public void addFocusables(ArrayList<View> views, int direction, int focusableMode) 添加可聚焦视图,只允许当前界面可聚焦
- public void addTouchables(ArrayList<View> views) 添加可触摸视图,只允许当前界面可触摸
- protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) 请求焦点的子类,只允许当前界面可调焦
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) 辅助功能事件的分发
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() 生成默认的布局参数
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) 生成布局参数
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) 检查布局参数
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) 生成布局参数
至此,ViewPager的类源码大体都分析完了,具体的详细内容需要自行看代码进行理解