ViewPager实现原理分析
ViewPager
是 Android 中用于展示多页面内容的控件,通常被用来实现滑动切换不同页面的功能,比如常见的应用启动引导页、广告轮播图或者多标签页的布局。ViewPager
是一个非常重要的控件,它提供了灵活的滑动效果和页面管理机制。
下面是基于 ViewPager
的源码分析,帮助理解其实现原理:
1. ViewPager 类定义
ViewPager
继承自 HorizontalScrollView
,这决定了它的滑动方向是水平的。
1public class ViewPager extends HorizontalScrollView {
2
3 private static final String TAG = "ViewPager";
4
5 // 页面适配器
6 private PagerAdapter mAdapter;
7
8 // 当前选中的页面索引
9 private int mCurItem;
10
11 // 子视图的容器
12 private final ArrayList<View> mViews = new ArrayList<>();
13
14 // 页面变化监听器
15 private OnPageChangeListener mOnPageChangeListener;
16
17 // 页面滚动监听器
18 private OnPageChangeInternalListener mOnPageChangeInternalListener = new OnPageChangeInternalListener();
19
20 // 构造函数
21 public ViewPager(Context context) {
22 this(context, null);
23 }
24
25 public ViewPager(Context context, AttributeSet attrs) {
26 super(context, attrs);
27 // 初始化操作
28 init();
29 }
30
31 private void init() {
32 // 设置滚动条为不可见
33 setHorizontalScrollBarEnabled(false);
34 // 设置不可缓存
35 setOverScrollMode(OVER_SCROLL_NEVER);
36 // 设置滚动监听器
37 setOnScrollChangeListener(mOnPageChangeInternalListener);
38 }
39
40 // 设置适配器
41 public void setAdapter(PagerAdapter adapter) {
42 // 清除之前的适配器
43 if (mAdapter != null) {
44 mAdapter.unregisterDataSetObserver(mObserver);
45 }
46 // 设置新的适配器
47 mAdapter = adapter;
48 if (adapter != null) {
49 // 注册数据集观察者
50 mAdapter.registerDataSetObserver(mObserver);
51 // 设置页面数量
52 setOffscreenPageLimit(mAdapter.getCount());
53 }
54 // 请求重新布局
55 requestLayout();
56 }
57
58 // 添加页面变化监听器
59 public void addOnPageChangeListener(OnPageChangeListener listener) {
60 mOnPageChangeListener = listener;
61 }
62
63 // 移除页面变化监听器
64 public void removeOnPageChangeListener(OnPageChangeListener listener) {
65 if (mOnPageChangeListener == listener) {
66 mOnPageChangeListener = null;
67 }
68 }
69
70 // 滑动到指定位置
71 public void setCurrentItem(int item, boolean smoothScroll) {
72 if (mAdapter == null || mAdapter.getCount() == 0) {
73 resetPosition();
74 return;
75 }
76 if (item >= mAdapter.getCount()) {
77 item = mAdapter.getCount() - 1;
78 } else if (item < 0) {
79 item = 0;
80 }
81 mCurItem = item;
82 scrollToItem(item, smoothScroll);
83 }
84
85 // 滚动到指定页面
86 private void scrollToItem(int item, boolean smoothScroll) {
87 // 计算偏移量
88 int offset = (getWidth() - getPaddingLeft() - getPaddingRight()) * item;
89 // 平滑滚动
90 if (smoothScroll) {
91 smoothScrollTo(offset, 0);
92 } else {
93 scrollTo(offset, 0);
94 }
95 }
96
97 // 其他方法...
98}
2. 设置适配器
ViewPager
需要通过 PagerAdapter
来填充页面数据,这是通过 setAdapter()
方法完成的。
1public void setAdapter(PagerAdapter adapter) {
2 // 清除之前的适配器
3 if (mAdapter != null) {
4 mAdapter.unregisterDataSetObserver(mObserver);
5 }
6 // 设置新的适配器
7 mAdapter = adapter;
8 if (adapter != null) {
9 // 注册数据集观察者
10 mAdapter.registerDataSetObserver(mObserver);
11 // 设置页面数量
12 setOffscreenPageLimit(mAdapter.getCount());
13 }
14 // 请求重新布局
15 requestLayout();
16}
3. 页面变化监听器
ViewPager
提供了 addOnPageChangeListener
和 removeOnPageChangeListener
方法来添加和移除页面变化监听器。
1public void addOnPageChangeListener(OnPageChangeListener listener) {
2 mOnPageChangeListener = listener;
3}
4
5public void removeOnPageChangeListener(OnPageChangeListener listener) {
6 if (mOnPageChangeListener == listener) {
7 mOnPageChangeListener = null;
8 }
9}
4. 滑动到指定位置
setCurrentItem
方法允许我们直接跳转到某个页面。
1public void setCurrentItem(int item, boolean smoothScroll) {
2 // ...
3 scrollToItem(item, smoothScroll);
4}
5. 滑动事件处理
ViewPager
重写了 HorizontalScrollView
的 onTouchEvent
方法,以便更好地处理触摸滑动事件。
1@Override
2public boolean onTouchEvent(MotionEvent ev) {
3 // ...
4 // 分发事件给页面适配器
5 if (mAdapter != null) {
6 mAdapter.onPageScrolled(mCurItem, positionOffset, positionOffsetPixels);
7 }
8 // ...
9 // 更新当前页面
10 updateCurrentItem();
11 // ...
12 return true;
13}
6. 页面更新
页面更新主要是通过 PagerAdapter
的 instantiateItem
和 destroyItem
方法来实现的。
1private void updateCurrentItem() {
2 // ...
3 // 根据当前索引加载页面
4 mAdapter.instantiateItem(this, mCurItem);
5 // ...
6 // 移除过期的页面
7 mAdapter.destroyItem(this, mCurItem, mViews.get(mCurItem));
8 // ...
9}
7. 数据集变更监听
PagerAdapter
的数据集发生变化时,ViewPager
会收到通知并相应地更新内部状态。
1private final DataSetObserver mObserver = new DataSetObserver() {
2 @Override
3 public void onChanged() {
4 // 数据集发生变化时的处理
5 // ...
6 }
7
8 @Override
9 public void onInvalidated() {
10 // 数据集无效时的处理
11 // ...
12 }
13};
总结
ViewPager
的核心功能是通过滑动来切换不同的页面。为了实现这一目标,ViewPager
内部维护了一个 PagerAdapter
实例,该实例负责页面数据的填充和更新。ViewPager
通过 PagerAdapter
的 instantiateItem
和 destroyItem
方法来加载和销毁页面。同时,ViewPager
还提供了一系列方法来处理页面的滑动和监听事件,以及页面数据变化的监听。
以上是对 ViewPager
的基本原理的概述,实际源码会更加复杂,涉及到更多的细节处理,但这些关键点足以帮助理解 ViewPager
的工作方式。
原文地址:https://blog.csdn.net/VitorLiu/article/details/140675408
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!