基于原生SwipeRefreshLayout修改为横向刷新组件

网上有很多横向滑动的组件但是都是自己去实现的。于是我就想能不能偷个懒直接用原生的改一下哈哈。结果还真行。只不过可能不支持ListView。ViewGroup(RecyclerView)都是可以的,要是想支持ListView自己去实现下他们提供的OnChildScrollUpCallback中的canChildScrollLeft方法判断是否能从左边往右边滑动,top被我改成了Left因为是横向滑动嘛。
先上代码
https://github.com/Darksiderlyd/HSwipeRefreshLayout

第一步:
首先看下拉组件的布局添加之前添加在顶部现在改一下添加到左边,以下是修改后的代码:

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int width = getMeasuredWidth();
        final int height = getMeasuredHeight();
        if (getChildCount() == 0) {
            return;
        }
        if (mTarget == null) {
            ensureTarget();
        }
        if (mTarget == null) {
            return;
        }
        final View child = mTarget;
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        final int childWidth = width - getPaddingLeft() - getPaddingRight();
        final int childHeight = height - getPaddingTop() - getPaddingBottom();
        child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
        int circleWidth = mCircleView.getMeasuredWidth();
        int circleHeight = mCircleView.getMeasuredHeight();
        mCircleView.layout(mCurrentTargetOffsetLeft, (height / 2 - circleHeight / 2),
                mCurrentTargetOffsetLeft + circleWidth, (height / 2 + circleHeight / 2));
    }

第二步:
修改各种与Y、Top、Vertical有关的参数

 private float mInitialMotionX;
 private float mInitialDownX;

1.这两个参数之前是Y改成X因为是横向滑动和X轴有关和Y轴无关。
然后修改这两个参数相关的位置的getY改成X的。
这些方法主要在以下几个方法中:

onInterceptTouchEvent()
onTouchEvent()

//此方法中的dy改为dx以下为修改后方法
@Override
public void onNestedScroll(final View target, final int dxConsumed, final int dyConsumed,
                           final int dxUnconsumed, final int dyUnconsumed) {
    // Dispatch up to the nested parent first
    dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
            mParentOffsetInWindow);

    // This is a bit of a hack. Nested scrolling works from the bottom up, and as we are
    // sometimes between two nested scrolling views, we need a way to be able to know when any
    // nested scrolling parent has stopped handling events. We do that by using the
    // 'offset in window 'functionality to see if we have been moved from the event.
    // This is a decent indication of whether we should take over theeventstream or not.
    final int dx = dxUnconsumed + mParentOffsetInWindow[0];
   if (dx < 0 && !canChildScrollUp()) {
        mTotalUnconsumed += Math.abs(dx);
        moveSpinner(mTotalUnconsumed);
    }
}
 
 
 @Override
 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
    // If we are in the middle of consuming, a scroll, then we want to move the spinner back up
    // before allowing the list to scroll
    if (dx > 0 && mTotalUnconsumed > 0) {
        if (dx > mTotalUnconsumed) {
            consumed[0] = dx - (int) mTotalUnconsumed;
            mTotalUnconsumed = 0;
           } else {
               mTotalUnconsumed -= dx;
               consumed[0] = dx;
           }
           moveSpinner(mTotalUnconsumed);
    }

    // If a client layout is using a custom start position for the circle
    // view, they mean to hide it again before scrolling the child view
    // If we get back to mTotalUnconsumed == 0 and there is more to go, hide
    // the circle so it isn't exposed if its blocking content is moved
     if (mUsingCustomStart && dx > 0 && mTotalUnconsumed == 0
             && Math.abs(dx - consumed[0]) > 0) {
         mCircleView.setVisibility(View.GONE);
    }

     // Now let our nested parent consume the leftovers
     final int[] parentConsumed = mParentScrollConsumed;
     if (dispatchNestedPreScroll(dx - consumed[0], dy - consumed[1], parentConsumed, null)) {
         consumed[0] += parentConsumed[0];
         consumed[1] += parentConsumed[1];
    }
}

2.把View.getTop() 都改为View.getLeft():

mCircleView.getLeft()

3.修改和Vertical相关的参数,修改canScrollVertically(参数小于0为从上往下滑动,大于零从下往上)为canScrollHorizontally(参数小于0为从左往右滑动,大于零从右往左),SCROLL_AXIS_VERTICAL修改为SCROLL_AXIS_HORIZONTAL,以下代码中去掉了ListView的判断看源码他只判断是否能上下滑动,所以要想适配ListView的话要去实现mChildScrollUpCallback.canChildScrollLeft方法

public boolean canChildScrollUp() {
        if (mChildScrollUpCallback != null) {
            return mChildScrollUpCallback.canChildScrollLeft(this, mTarget);
        }
//        if (mTarget instanceof ListView) {
//            return ListViewCompat.canScrollList((ListView) mTarget, -1);
            return mChildScrollUpCallback.canChildScrollLeft(this, mTarget);
//        }
        return mTarget.canScrollHorizontally(-1);
}
    
// NestedScrollingParent
 @Override
 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
     return isEnabled() && !mReturningToStart && !mRefreshing
             && (nestedScrollAxes & ViewCompat.SCROLL_AXIS_HORIZONTAL) != 0;
 }

@Override
public void onNestedScrollAccepted(View child, View target, int axes) {
    // Reset the counter of how much leftover scroll needs to beconsumed.
       mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes);
       // Dispatch up to the nested parent
       startNestedScroll(axes & ViewCompat.SCROLL_AXIS_HORIZONTAL);
       mTotalUnconsumed = 0;
       mNestedScrollInProgress = true;
   }

4.修改完成后试了一下效果感觉下拉组件就是那个圆圈下拉的距离和手指滑动不协调,看下源码有一个DRAG_RATE(阻尼系数)有一个这个参数改大一点。

参考:

https://www.jianshu.com/p/1f0d44faed5f

https://blog.csdn.net/birthmarkqiqi/article/details/79564289

猜你喜欢

转载自blog.csdn.net/u011148116/article/details/103312994