web-dev-qa-db-ja.com

RecyclerViewスクロールアップ/ダウンリスナー

ユーザーがRecyclerViewで下にスクロールしたか上にスクロールしたかをどのようにして知ることができますか?

RecyclerView#OnScrollListenerで試しましたが、これは垂直スクロールの量とスクロール状態を示します。スクロール状態がアイドルのときにドラッグを開始し、スクロール位置を開始したときに最後のスクロール位置を取得するにはどうすればよいですか。

ありがとうございました。

37
Libin

この方法を試してください:

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;

}
29
Xcihnegn

受け入れられた答えは問題なく動作しますが、@ 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
        }
    }
});
76
Reaz Murshed

Recyclerviewが下にスクロールされる場合はレイアウトを非表示にし、recyclerviewが上にスクロールされる場合はレイアウトを表示したかったのです。私はいくつかの考えをし、この論理を思いつきました。変数yはグローバルな静的整数です。 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);
                    }
                }
            }
        });
10
Shahid Sarwar

アダプタの助けを借りてスクロール方向を検出できる別の簡単なソリューション:

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が呼び出されるまで、道順を不連続に知らせます。

2

すべてのタイプのスクロールリスナーで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());
    }
};