RecyclerView滚动了UP / DOWN监听器

时间:2015-03-13 02:45:29

标签: android android-recyclerview

我们如何知道用户是否在RecyclerView向下或向上滚动?

我尝试了RecyclerView#OnScrollListener,它给出了垂直滚动量和滚动状态。当滚动状态空闲时,我们如何在开始拖动和滚动位置时获得最后一个滚动位置。

谢谢。

6 个答案:

答案 0 :(得分:74)

接受的答案很好,但@MaciejPigulski在下面的评论中提供了更清晰,更整洁的解决方案。我只是把它作为答案在这里。这是我的工作代码。

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if (dy > 0) {
            // Scrolling up
        } else {
            // Scrolling down
        }
    }

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
            // Do something
        } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
            // Do something
        } else {
            // Do something
        }
    }
});

答案 1 :(得分:28)

尝试这种方式:

private static int firstVisibleInListview;

firstVisibleInListview = yourLayoutManager.findFirstVisibleItemPosition();

在滚动侦听器中:

public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
{
    super.onScrolled(recyclerView, dx, dy);

    int currentFirstVisible = yourLayoutManager.findFirstVisibleItemPosition();

    if(currentFirstVisible > firstVisibleInListview)
       Log.i("RecyclerView scrolled: ", "scroll up!");
    else
       Log.i("RecyclerView scrolled: ", "scroll down!");  

    firstVisibleInListview = currentFirstVisible;

}

答案 2 :(得分:9)

如果向下滚动Recyclerview,我想隐藏布局,然后如果向上滚动回收器视图则使其可见。我做了一些思考,想出了这个逻辑。 变量y是全局静态int。不要忘记将y声明为static int y;

我希望它有助于某人:)

 mRecyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(lLayout) {
           @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            // super.onScrolled(recyclerView, dx, dy);
                y=dy;
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(mRecyclerView.SCROLL_STATE_DRAGGING==newState){
                    //fragProductLl.setVisibility(View.GONE);
                }
                if(mRecyclerView.SCROLL_STATE_IDLE==newState){
                   // fragProductLl.setVisibility(View.VISIBLE);
                    if(y<=0){
                        fragProductLl.setVisibility(View.VISIBLE);
                    }
                    else{
                        y=0;
                        fragProductLl.setVisibility(View.GONE);
                    }
                }
            }
        });

答案 3 :(得分:2)

另一个可以在适配器的帮助下检测滚动方向的简单解决方案:

class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyViewHolder> {
    int lastItemPosition = -1;

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        if (position > lastItemPosition) {
            // Scrolled Down
        }
        else {
            // Scrolled Up
        }
        lastItemPosition = position;
     }
}

^在滚动时执行项目动画时很有帮助。

PS:这将不断告诉您指示,直到进一步onBindViewHolder调用。

答案 4 :(得分:1)

我的CustomRecyclerView实现了所有类型的滚动侦听器

public class CustomRecyclerView extends RecyclerView
{
private boolean mIsScrolling;
private boolean mIsTouching;
private OnScrollListener mOnScrollListener;
private Runnable mScrollingRunnable;
private int y = 0;

public abstract static class OnScrollListener
{
    void onScrollChanged(CustomRecyclerView RvView, int x, int y, int oldX, int oldY)
    {
        //if you need just override this method
    }

    void onEndScroll(CustomRecyclerView RvView)
    {
        //if you need just override this method
    }

    protected abstract void onGoUp();

    protected abstract void onGoDown();
}

public CustomRecyclerView(final Context context)
{
    super(context);
}

public CustomRecyclerView(final Context context, @Nullable final AttributeSet attrs)
{
    super(context, attrs);
}

public CustomRecyclerView(final Context context, @Nullable final AttributeSet attrs, final int defStyle)
{
    super(context, attrs, defStyle);
}

@Override
public boolean dispatchTouchEvent(MotionEvent iEv)
{
    if (isEnabled())
    {
        processEvent(iEv);
        super.dispatchTouchEvent(iEv);
        return true; //to keep receive event that follow down event
    }

    return super.dispatchTouchEvent(iEv);
}

private void processEvent(final MotionEvent iEv)
{
    switch (iEv.getAction())
    {
        case MotionEvent.ACTION_DOWN:
            y = (int) iEv.getY();
            break;

        case MotionEvent.ACTION_UP:
            y = (int) iEv.getY();

            if (mIsTouching && !mIsScrolling && mOnScrollListener != null)
            {
                mOnScrollListener.onEndScroll(this);
            }

            mIsTouching = false;
            break;
        case MotionEvent.ACTION_MOVE:
            mIsTouching = true;
            mIsScrolling = true;

            int newY = (int) iEv.getY();
            int difY = y - newY;

            int MAX_VALUE = 200;
            int MIN_VALUE = -200;
            if (difY > MAX_VALUE)
            {
                if (mOnScrollListener != null)
                {
                    mOnScrollListener.onGoDown();
                }
                y = newY;
            }
            else if (difY < MIN_VALUE)
            {
                if (mOnScrollListener != null)
                {
                    mOnScrollListener.onGoUp();
                }
                y = newY;
            }

            break;
    }
}

@Override
protected void onScrollChanged(int iX, int iY, int iOldX, int iOldY)
{
    super.onScrollChanged(iX, iY, iOldX, iOldY);

    if (Math.abs(iOldX - iX) > 0)
    {
        if (mScrollingRunnable != null)
        {
            removeCallbacks(mScrollingRunnable);
        }

        mScrollingRunnable = () ->
        {
            if (mIsScrolling && !mIsTouching && mOnScrollListener != null)
            {
                mOnScrollListener.onEndScroll(CustomRecyclerView.this);
            }

            mIsScrolling = false;
            mScrollingRunnable = null;
        };

        postDelayed(mScrollingRunnable, 200);
    }

    if (mOnScrollListener != null)
    {
        mOnScrollListener.onScrollChanged(this, iX, iY, iOldX, iOldY);
    }
}

public void scrollToView(final View iV)
{
    // Get deepChild Offset
    Point childOffset = new Point();
    getDeepChildOffset(CustomRecyclerView.this, iV.getParent(), iV, childOffset);
    // Scroll to child.

    CustomRecyclerView.this.scrollToY(childOffset.y);
}

private void getDeepChildOffset(final ViewGroup mainParent, final ViewParent parent, final View child, final Point accumulatedOffset)
{
    ViewGroup parentGroup = (ViewGroup) parent;
    accumulatedOffset.x += child.getLeft();
    accumulatedOffset.y += child.getTop();
    if (parentGroup.equals(mainParent))
    {
        return;
    }
    getDeepChildOffset(mainParent, parentGroup.getParent(), parentGroup, accumulatedOffset);
}

public void scrollToY(final int iY)
{
    CustomRecyclerView.this.postDelayed(() ->
    {
        int x = 0;
        int y = iY;
        ObjectAnimator xTranslate = ObjectAnimator.ofInt(CustomRecyclerView.this, "scrollX", x);
        ObjectAnimator yTranslate = ObjectAnimator.ofInt(CustomRecyclerView.this, "scrollY", y);

        AnimatorSet animators = new AnimatorSet();
        animators.setDuration(500L);
        animators.playTogether(xTranslate, yTranslate);
        animators.addListener(new Animator.AnimatorListener()
        {

            @Override
            public void onAnimationStart(Animator arg0)
            {
                // noting
            }

            @Override
            public void onAnimationRepeat(Animator arg0)
            {
                // noting
            }

            @Override
            public void onAnimationEnd(Animator arg0)
            {
                // noting
            }

            @Override
            public void onAnimationCancel(Animator arg0)
            {
                // noting
            }
        });
        animators.start();
    }, 300);
}

public void scrollToTop()
{
    scrollToY(0);
}

public void setOnRvScrollListener(OnScrollListener mOnEndScrollListener)
{
    this.mOnScrollListener = mOnEndScrollListener;
}
}

还有使用样本

private void setRecyclerViewSettings()
{
    mRv.setLayoutManager(new LinearLayoutManager(getActivity()));
    mRv.setOnRvScrollListener(mScrollListener);
}

private CustomRecyclerView.OnScrollListener mScrollListener = new CustomRecyclerView.OnScrollListener()
{
    @Override
    protected void onGoUp()
    {
        AppUtils.hideKeyboard(getContext(), mRvDynamicFormQuestions.getFocusedChild());
    }

    @Override
    protected void onGoDown()
    {
        AppUtils.hideKeyboard(getContext(), mRvDynamicFormQuestions.getFocusedChild());
    }
};

答案 5 :(得分:1)

这段代码对我有用

private var nearmeListScrollListener = object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

          
                if (recyclerView.scrollState == RecyclerView.SCROLL_STATE_SETTLING)
                    if (dy > 0) {
                        layout_vendros_list_header.hide()
                         layout_vendros_list_header.animate().translationY(1f)
                    } else if (dy < 0) {
                        layout_vendros_list_header.show()
                        layout_vendros_list_header.animate().translationY(0f)
                    }

        }
    }
    ```