Подтвердить что ты не робот

RecyclerView scrollToPosition не запускает scrollListener

Я использую RecyclerView со ScrollListener:

mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener()
{
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState)
        {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy)
        {
            super.onScrolled(recyclerView, dx, dy);
            // Do my logic
        }
 });

Когда я прокручиваю пальцем, прослушиватель прокрутки срабатывает нормально.

Но когда я прокручиваю прогматически, вот так:

mRecyclerView.scrollToPosition(LAST_POSITION);

Слушатель прокрутки не запускается.

4b9b3361

Ответ 1

Это известная проблема. Это вызвано тем фактом, что RecyclerView не знает, как LayoutManager будет обрабатывать свиток или если он будет обрабатывать его вообще.

В следующем выпуске вы получите вызов onScrolled, если первая и последняя дочерняя позиция будут изменены после макета (что обычно является результатом вызова прокрутки в позицию).

К сожалению, dx и dy будут равны 0, потому что RecyclerView не знает, сколько прокрутил менеджер макетов для обработки запроса scrollTo. Кроме того, вы также можете использовать обратный вызов прокрутки ViewTreeObserver.

Ответ 2

Я столкнулся с той же проблемой и нашел обходной путь, который должен использовать smoothScrollToPosition в менеджере компоновки. Этот метод запускает прослушиватель прокрутки. Поэтому в основном это то, что я использую:

recyclerView.scrollToPosition(recyclerAdapter.getItemCount() - 1);

и теперь я изменил это:

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null, recyclerAdapter.getItemCount() - 1);

и он отлично работает для меня.

Ответ 3

Это немного рудиментарно, но вы можете попробовать этот подкласс RecyclerView:

public class PatchedRecyclerView extends RecyclerView {

    private OnScrollListener listener;

    public PatchedRecyclerView(Context context) {
        super(context);
    }

    public PatchedRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PatchedRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setOnScrollListener(OnScrollListener listener) {
        super.setOnScrollListener(listener);
        this.listener = listener;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int preFirstChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(0)).getPosition() : -1;
        int preLastChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(getChildCount() - 1)).getPosition() : -1;
        super.onLayout(changed, l, t, r, b);
        int postFirstChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(0)).getPosition() : -1;
        int postLastChildPosition = getChildCount() != 0 ? getChildViewHolder(getChildAt(getChildCount() - 1)).getPosition() : -1;

        // TODO: Insert proper DX and DY values
        if (preFirstChildPosition != postFirstChildPosition || preLastChildPosition != postLastChildPosition)
            listener.onScrolled(this, 0, 0);
    }
}

Ответ 4

int mFirst=0, mLast=0;

recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
        mLast = llm.findLastCompletelyVisibleItemPosition();
        mFirst = llm.findFirstCompletelyVisibleItemPosition();
    }
});

imgRight.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
        llm.scrollToPositionWithOffset(mLast + 1, List.length());
    }
});

imgLeft.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        LinearLayoutManager llm = (LinearLayoutManager) recyclerview.getLayoutManager();
        llm.scrollToPositionWithOffset(mFirst - 1, List.length());
    }
});

Ответ 5

Чтобы явно вызвать onScrollListener над просмотром ресайклера, используйте:

recyclerView.smoothScrollBy(x, y);
//x is the horizontal displacement and y is vertical displacement.

Ответ 6

Я не мог использовать smoothScrollToPosition (у нас были некоторые проблемы с ним в прошлом), и в зависимости от положения первого элемента казалось ненадежным, поэтому я закончил использование yigit (он уже выпущен), к сожалению, он не всегда работал (я не уверен, почему).

Итак, я закончил использовать прослушиватель прокрутки, который я добавил ранее в RecyclerView, к сожалению, я не могу найти источник этого решения.
Я не думаю, что вы должны использовать этого слушателя, если вам нужен постоянный, к счастью, мне нужно слушать только в определенное время.

Переопределить RecyclerView:

public class MyRecyclerView extends RecyclerView {

    public interface OnScrollStoppedListener{
        void onScrollStopped();
    }

    private static final int NEW_CHECK_INTERVAL = 100;
    private OnScrollStoppedListener mOnScrollStoppedListener;
    private Runnable mScrollerTask;
    private int mInitialPosition;

    public MyRecyclerView(Context context) {
        super(context);
        init();
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    private void init() {
        mScrollerTask = new Runnable() {
            public void run() {
                int newPosition = getScrollY();
                if(mInitialPosition - newPosition == 0) {//has stopped
                    if(mOnScrollStoppedListener !=null) {
                        mOnScrollStoppedListener.onScrollStopped();
                    }
                } else {
                    startScrollerTask();
                }
            }
        };
    }

    public void setOnScrollStoppedListener(MyRecyclerView.OnScrollStoppedListener listener){
        mOnScrollStoppedListener = listener;
    }

    public void startScrollerTask() {
        mInitialPosition = getScrollY();
        postDelayed(mScrollerTask, NEW_CHECK_INTERVAL);
    }

}  

Использование:

myRecyclerView.setOnScrollStoppedListener(new MyRecyclerView.OnScrollStoppedListener() {
    @Override
    public void onScrollStopped() {
        // Do your thing
    }
});

myRecyclerView.startScrollerTask();

Ответ 7

Muito legal seu conselho.

 Button maisOpcoes = (Button) findViewById(R.id.maisOpcoes);
        maisOpcoes.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null , recyclerViewTmd.getItemCount() - 1);
                maisOpcoes.setVisibility(View.GONE);
            }
        });