之前一直是使用自定义的下拉控件来自定义ListView 和GridView的刷新,但是既然google出了个SwipeRefreshLayout 那为何不用呢?
初始使用下来感觉还是不错,但是在一个需求面前就遇到了问题:
需求: 可下拉刷新的列表,单独项可侧滑删除
还以为很简单的一个功能却遇到了问题,在侧滑的时候总是能触发下拉刷新,当下拉的时候,Item中的事件就断掉了。于是就找了下源码看到如下代码:
@Override public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (action) {
//略
case MotionEvent.ACTION_MOVE: if (mActivePointerId == INVALID_POINTER) { Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id."); return false; } final float y = getMotionEventY(ev, mActivePointerId); if (y == -1) { return false; } final float yDiff = y - mInitialDownY; if (yDiff > mTouchSlop && !mIsBeingDragged) {//罪魁祸首在这里 mInitialMotionY = mInitialDownY + mTouchSlop; mIsBeingDragged = true; mProgress.setAlpha(STARTING_PROGRESS_ALPHA); } break; } return mIsBeingDragged; }
原来罪魁祸首在于SwipRefreshLayout 在OnInterceptTouchEvent 中 一旦Y轴超过8像素则 完全吃下了整个消息流程,(请不要问我View里设置ontouch 或者 ontouchevent 为什么无效),为了改变这个,我们对OnInterceptTouchEvent 修改如下(我是自定义了SwipRefreshLayout 类):
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { ensureTarget(); final int action = MotionEventCompat.getActionMasked(ev); if (mReturningToStart && action == MotionEvent.ACTION_DOWN) { mReturningToStart = false; } if (!isEnabled() || mReturningToStart || canChildScrollUp() || mRefreshing) { // Fail fast if we're not in a state where a swipe is possible return false; } switch (action) { case MotionEvent.ACTION_DOWN: setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true); mActivePointerId = MotionEventCompat.getPointerId(ev, 0); mIsBeingDragged = false; mIsBeingHorizontalDragged = false; final float initialDownY = getMotionEventY(ev, mActivePointerId); final float initialDownX = getMotionEventX(ev, mActivePointerId); if (initialDownY == -1) { return false; } mInitialDownX = initialDownX; mInitialDownY = initialDownY; break; case MotionEvent.ACTION_MOVE: if (mActivePointerId == INVALID_POINTER) { Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id."); return false; } final float y = getMotionEventY(ev, mActivePointerId); final float x = getMotionEventX(ev, mActivePointerId); if (y == -1) { return false; } final float yDiff = y - mInitialDownY; final float xDiff = x - mInitialDownX; if(!mIsBeingHorizontalDragged&& Math.abs(xDiff) > 2*mTouchSlop&&!mIsBeingDragged){//不一定要2*mTouchSlop mIsBeingHorizontalDragged = true; } if (yDiff > mTouchSlop && !mIsBeingDragged&&!mIsBeingHorizontalDragged) { mInitialMotionY = mInitialDownY + mTouchSlop; mIsBeingDragged = true; mProgress.setAlpha(STARTING_PROGRESS_ALPHA); } break; case MotionEventCompat.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mIsBeingDragged = false; mIsBeingHorizontalDragged = false; mActivePointerId = INVALID_POINTER; break; } return mIsBeingDragged; }
有几个 变量需要声明下,如上修改,则可区分 侧滑还是竖滑,侧滑的功能可以开心用了