Created
June 9, 2015 04:18
-
-
Save geminiwen/9fda4ff6b84ffd3691e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.segmentfault.app.view; | |
import android.content.Context; | |
import android.support.v4.view.MotionEventCompat; | |
import android.support.v4.view.NestedScrollingChild; | |
import android.support.v4.view.NestedScrollingChildHelper; | |
import android.support.v4.view.ViewCompat; | |
import android.support.v4.widget.SwipeRefreshLayout; | |
import android.util.AttributeSet; | |
import android.view.MotionEvent; | |
import android.view.ViewConfiguration; | |
/** | |
* Created by geminiwen on 15/6/2. | |
*/ | |
public class NestedScrollSwipeRefreshLayout extends SwipeRefreshLayout implements NestedScrollingChild{ | |
private static final int INVALID_POINTER = -1; | |
private int mTouchSlop; | |
private int mActivePointerId = INVALID_POINTER; | |
private NestedScrollingChildHelper mChildHelper; | |
public NestedScrollSwipeRefreshLayout(Context context) { | |
this(context, null); | |
} | |
public NestedScrollSwipeRefreshLayout(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
mChildHelper = new NestedScrollingChildHelper(this); | |
setNestedScrollingEnabled(true); | |
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); | |
} | |
@Override | |
public void setNestedScrollingEnabled(boolean enabled) { | |
mChildHelper.setNestedScrollingEnabled(enabled); | |
} | |
@Override | |
public boolean isNestedScrollingEnabled() { | |
return mChildHelper.isNestedScrollingEnabled(); | |
} | |
@Override | |
public boolean startNestedScroll(int axes) { | |
return mChildHelper.startNestedScroll(axes); | |
} | |
@Override | |
public void stopNestedScroll() { | |
mChildHelper.stopNestedScroll(); | |
} | |
@Override | |
public boolean hasNestedScrollingParent() { | |
return mChildHelper.hasNestedScrollingParent(); | |
} | |
@Override | |
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { | |
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); | |
} | |
@Override | |
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { | |
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); | |
} | |
@Override | |
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { | |
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); | |
} | |
@Override | |
public boolean dispatchNestedPreFling(float velocityX, float velocityY) { | |
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); | |
} | |
private float mLastMotionY; | |
private final int[] mScrollOffset = new int[2]; | |
private final int[] mScrollConsumed = new int[2]; | |
private boolean mIsBeginDrag = false; | |
@Override | |
public boolean onInterceptTouchEvent(MotionEvent ev) { | |
final int action = MotionEventCompat.getActionMasked(ev); | |
switch (action) { | |
case MotionEvent.ACTION_DOWN: { | |
mActivePointerId = MotionEventCompat.getPointerId(ev, 0); | |
final float initialDownY = getMotionEventY(ev, mActivePointerId); | |
if (initialDownY == -1) { | |
return false; | |
} | |
mLastMotionY = initialDownY; | |
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); | |
super.onInterceptTouchEvent(ev); | |
mIsBeginDrag = false; | |
break; | |
} | |
case MotionEvent.ACTION_MOVE: { | |
if (mActivePointerId == INVALID_POINTER) { | |
return false; | |
} | |
final float y = getMotionEventY(ev, mActivePointerId); | |
if (y == -1) { | |
return false; | |
} | |
int deltaY = (int)(mLastMotionY - y); | |
mLastMotionY = y; | |
if (Math.abs(deltaY) >= mTouchSlop) { | |
mIsBeginDrag = true; | |
} | |
if (mIsBeginDrag && dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { | |
mLastMotionY -= mScrollOffset[1]; | |
deltaY -= mScrollConsumed[1]; | |
ev.offsetLocation(0, mScrollConsumed[1]); | |
if (dispatchNestedScroll(0, 0, 0, deltaY, mScrollOffset)) { | |
mLastMotionY -= mScrollOffset[1]; | |
ev.offsetLocation(0, mScrollOffset[1]); | |
} | |
return false; | |
} else { | |
return super.onInterceptTouchEvent(ev); | |
} | |
} | |
case MotionEvent.ACTION_CANCEL: | |
case MotionEvent.ACTION_UP: { | |
stopNestedScroll(); | |
mActivePointerId = INVALID_POINTER; | |
mIsBeginDrag = false; | |
return super.onInterceptTouchEvent(ev); | |
} | |
} | |
return super.onInterceptTouchEvent(ev); | |
} | |
private float getMotionEventY(MotionEvent ev, int activePointerId) { | |
final int index = MotionEventCompat.findPointerIndex(ev, activePointerId); | |
if (index < 0) { | |
return -1; | |
} | |
return MotionEventCompat.getY(ev, index); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SwipeRefreshLayout本身就已经实现了NestedScrollingChild接口的