PullToRefreshListView原理解析(二)
来源:互联网 发布:mac怎么分盘储存文件 编辑:程序博客网 时间:2024/06/06 17:11
PullToRefreshListView的父类是PullToRefreshAdapterViewBase<T extends AbsListView>,PullToRefreshAdapterViewBase的父类是
PullToRefreshBase<T extends View>。
PullToRefreshBase是公共父类,它的结构如下。从上往下,分别为headView,泛型T,footViewheadView和footView不用说了,上拉或者下拉显示出来的UI。至于显示成什么样子,那事他们自己的事,重点是PullToRefreshBase要告诉他们什么时候是
上拉了什么时候是下拉了。PullToRefreshListView的重点也都在这个类里面。至于不需要显示headView和footView时,怎么操作那是泛型T的事。泛型T就是
需要对什么控件添加上拉和下拉效果,可能是WebView,也可能是ListView,这里提高了扩展性。最终PullToRefreshListView传入的泛型T就是ListView。所以
PullToRefreshBase的重点就是什么时候拦截事件来通知headView和footView执行上拉下拉效果。1.拦截事件onInterceptTouchEvent
public final boolean onInterceptTouchEvent(MotionEvent event) {if (!isPullToRefreshEnabled()) {return false;}final int action = event.getAction();// 事件事if (mMode == Mode.REFROTATE && action == MotionEvent.ACTION_UP) {}if (action == MotionEvent.ACTION_CANCEL|| action == MotionEvent.ACTION_UP) {mIsBeingDragged = false;return false;}if (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) {return true;}switch (action) {case MotionEvent.ACTION_MOVE: {// If we're refreshing, and the flag is set. Eat all MOVE eventsif (!mScrollingWhileRefreshingEnabled && isRefreshing()) {return true;}if (isReadyForPull()) {final float y = event.getY(), x = event.getX();final float diff, oppositeDiff, absDiff;// We need to use the correct values, based on scroll// directionswitch (getPullToRefreshScrollDirection()) {case HORIZONTAL:diff = x - mLastMotionX;oppositeDiff = y - mLastMotionY;break;case VERTICAL:default:diff = y - mLastMotionY;oppositeDiff = x - mLastMotionX;break;}absDiff = Math.abs(diff);if (absDiff > mTouchSlop&& (!mFilterTouchEvents || absDiff > Math.abs(oppositeDiff))) {if (mMode.showHeaderLoadingLayout() && diff >= 1f&& isReadyForPullStart()) {mLastMotionY = y;mLastMotionX = x;mIsBeingDragged = true;if (mMode == Mode.BOTH || mMode == Mode.FLIP_ROTATE) {mCurrentMode = Mode.PULL_FROM_START;}} else if (mMode.showFooterLoadingLayout() && diff <= -1f&& isReadyForPullEnd()) {mLastMotionY = y;mLastMotionX = x;mIsBeingDragged = true;if (mMode == Mode.BOTH || mMode == Mode.FLIP_ROTATE|| mMode == Mode.REFROTATE) {mCurrentMode = Mode.PULL_FROM_END;}}}}break;}case MotionEvent.ACTION_DOWN: {if (isReadyForPull()) {mLastMotionY = mInitialMotionY = event.getY();mLastMotionX = mInitialMotionX = event.getX();mIsBeingDragged = false;}break;}}return mIsBeingDragged;}
1.首先ACTION_DOWN肯定要返回false,因为按下时还不知道是否要显示headView或者footView,要是返回true,滑动事件就传递不到ListView了。
2.action != MotionEvent.ACTION_DOWN && mIsBeingDraggedACTION_MOVE时,是否返回true,主要看mIsBeingDragged是否为true,那它什么时候为true呢。2.1 isRefreshing()的时候public final boolean isRefreshing() {return mState == State.REFRESHING || mState == State.MANUAL_REFRESHING;}2.2if (absDiff > mTouchSlop&& (!mFilterTouchEvents || absDiff > Math.abs(oppositeDiff))) {if (mMode.showHeaderLoadingLayout() && diff >= 1f&& isReadyForPullStart()) {mLastMotionY = y;mLastMotionX = x;mIsBeingDragged = true;if (mMode == Mode.BOTH || mMode == Mode.FLIP_ROTATE) {mCurrentMode = Mode.PULL_FROM_START;}} else if (mMode.showFooterLoadingLayout() && diff <= -1f&& isReadyForPullEnd()) {mLastMotionY = y;mLastMotionX = x;mIsBeingDragged = true;if (mMode == Mode.BOTH || mMode == Mode.FLIP_ROTATE|| mMode == Mode.REFROTATE) {mCurrentMode = Mode.PULL_FROM_END;}}}
只要有上下滑动就能进入第一层if,
absDiff > Math.abs(oppositeDiff)就是判断滑动时垂直移动距离大于水平移动距离,即上下滑动。
里面一层if主要就是判断,
mMode.showHeaderLoadingLayout()
判断mode,真正使用时自己会设置的,只要设置没问题就是true.
diff >= 1f
就不说了
isReadyForPullStart()是抽象方法,看子类。子类主要在isFirstItemVisible方法
private boolean isFirstItemVisible() {final Adapter adapter = mRefreshableView.getAdapter();if (null == adapter || adapter.isEmpty()) {if (DEBUG) {Log.d(LOG_TAG, "isFirstItemVisible. Empty View.");}return true;} else {/** * This check should really just be: * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView * internally use a HeaderView which messes the positions up. For * now we'll just add one to account for it and rely on the inner * condition which checks getTop(). */if (mRefreshableView.getFirstVisiblePosition() <= 1) {final View firstVisibleChild = mRefreshableView.getChildAt(0);if (firstVisibleChild != null) {return firstVisibleChild.getTop() >= mRefreshableView.getTop();}}}return false;}可以看到,泛型是ListView时,就是判断是不是在最顶部。另一个if代码块意思也差不多
2.执行事件onTouchEvent
不用想也知道,当onInterceptTouchEvent返回true时(mIsBeingDragged为true),onTouchEvent肯定要做处理了.比如ACTION_MOVE的时候
case MotionEvent.ACTION_MOVE: {if (mIsBeingDragged) {mLastMotionY = event.getY();mLastMotionX = event.getX();pullEvent();return true;}break;}执行pullEvent,主要就是一系列计算,让headView或者footView滑动。这里就不说了
over
阅读全文
0 0
- PullToRefreshListView原理解析(二)
- PullToRefreshListView原理解析(一)
- Android-开发-PullToRefreshListView原理
- Android-开发-PullToRefreshListView原理
- nginx配置解析原理(二)
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- PullToRefreshListView
- pullToRefreshListView
- PulltorefreshListview
- Intellij 中的git操作
- [C# 网络编程系列] 专题二:HTTP协议详解
- WebRTC视频帧渲染前处理——视频帧裁剪
- leetcode1.Two Sum
- 算法第2篇——插入排序
- PullToRefreshListView原理解析(二)
- 字符串的连接,以及字符串大小写的转换
- getWidth和getMeasureWidth区别
- java Collections.sort()排序。List排序
- 用PL/SQL Developer创建Oracle触发器以及触发器的一点点知识与出现的问题
- Handlebars一些
- 普通按钮和图片按钮
- spring mvc运行原理
- spark mllib 的数据预处理