只是一个搬运工
代码(自己加的注释,好多不懂,勿喷)
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();
}
/**
* 实现一些跟NestedScrollingParent交互的一些方法,通知父view
* @param axes
* @return
*/
@Override
public boolean startNestedScroll (int axes) {
return mChildHelper.startNestedScroll(axes);
}
/**
* 结束整个流程。
*/
@Override
public void stopNestedScroll () {
mChildHelper.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent () {
return mChildHelper.hasNestedScrollingParent();
}
/**
* 向父view汇报滚动情况,包括子view消费的部分和子view没有消费的部分。
* 这个函数一般在子view处理scroll后调用。
* @param dxConsumed
* @param dyConsumed
* @param dxUnconsumed
* @param dyUnconsumed
* @param offsetInWindow
* @return 如果父view接受了它的滚动参数,进行了部分消费,则这个函数返回true,否则为false。
*/
@Override
public boolean dispatchNestedScroll (int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int [] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
/**
* 一般在MotionEvent.Move里调用 通知父View滑动的距离
*
*
* 由于窗体进行了移动,如果你记录了手指最后的位置,需要根据第四个参数offsetInWindow计算偏移量,
* 才能保证下一次的touch事件的计算是正确的。
* 一般在子view处理scroll前调用
* @param dx
* @param dy
* @param consumed 第一个元素是父view消费的x方向的滚动距离;第二个元素是父view消费的y方向的滚动距离
* @param offsetInWindow 子View的窗体偏移量
* @return 如果父view接受了它的滚动参数,进行了部分消费,则这个函数返回true,否则为false
*/
@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 ;
}
/**
* 正在拖动,父view消耗了部分view,就交给父view处理
* mScrollOffset[1] 子view窗口y轴的偏移量
* mScrollOffset[1] 父view消费的y轴偏移量
*/
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);
}
/**
* 返回 坐标的y值
* 解决多点触摸的问题
* @param ev
* @param activePointerId
* @return
*/
private float getMotionEventY (MotionEvent ev, int activePointerId) {
final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
if (index < 0 ) {
return -1 ;
}
return MotionEventCompat.getY(ev, index);
}
}