Modified to horizontal refresh component based on native SwipeRefreshLayout

There are many horizontal sliding components on the Internet, but they are all implemented by themselves. So I wondered if I could be lazy and change it directly with the original haha. The result is really good. It's just that ListView may not be supported. ViewGroup (RecyclerView) are all possible. If you want to support ListView to implement the canChildScrollLeft method in OnChildScrollUpCallback they provide to determine whether it can slide from left to right, I changed top to Left because it is horizontal sliding.
First go to the code
https://github.com/Darksiderlyd/HSwipeRefreshLayout

The first step:
first look at the layout of the drop-down component before adding it at the top, now change it and add it to the left, the following is the modified code:

@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));
    }

Step 2:
Modify various parameters related to Y, Top, and Vertical

 private float mInitialMotionX;
 private float mInitialDownX;

1. Before these two parameters, Y was changed to X because the lateral sliding is related to the X axis and has nothing to do with the Y axis.
Then modify the position of the two parameters related to getY changed to X.
These methods are mainly in the following methods:

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. Change all View.getTop() to View.getLeft():

mCircleView.getLeft()

3. Modify the parameters related to Vertical, modify canScrollVertically (parameters less than 0 to slide from top to bottom, greater than zero from bottom to top) to canScrollHorizontally (parameters less than 0 to slide from left to right, greater than zero from right to left), SCROLL_AXIS_VERTICAL is modified to SCROLL_AXIS_HORIZONTAL. In the following code, the judgment of ListView is removed. Looking at the source code, he only judges whether it can slide up and down, so if you want to adapt to ListView, you need to implement the mChildScrollUpCallback.canChildScrollLeft method

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. After the modification, I tried the effect. I feel that the drop-down component is that the distance of the circle is not in harmony with the sliding of the finger. Look at the source code, there is a DRAG_RATE (damping coefficient) and this parameter is changed a bit larger.

reference:

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

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

Guess you like

Origin blog.csdn.net/u011148116/article/details/103312994