RecyclerView scrollToPosition not trigger scrollListener

前端 未结 8 2141
予麋鹿
予麋鹿 2021-02-01 03:35

I\'m using RecyclerView, with ScrollListener:

mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener()
{
        @Override
        public void onScr         


        
相关标签:
8条回答
  • 2021-02-01 03:57

    This is a known issue. It is caused by the fact that RecyclerView does not know how LayoutManager will handle the scroll or if it will handle it at all.

    In the next release, you'll receive a call to onScrolled if first and or last child position changes after a layout (which is generally the result of calling scroll to position).

    Unfortunately, dx and dy will be 0 because RecyclerView does not really know how much layout manager did scroll to handle scrollTo request. Alternatively, you can also use the the ViewTreeObserver's scroll callback.

    0 讨论(0)
  • 2021-02-01 04:02

    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);
                }
            });
    
    0 讨论(0)
  • 2021-02-01 04:03

    I could not use the smoothScrollToPosition (we had some problems with it in the past) and depending on the position of the first item seemed unreliable, so I ended up using yigit's answer (it has been released already), unfortunately it didn't always work (I am not sure why).

    So I ended up using a scroll listener I've added previously to the RecyclerView, sadly I cannot find the origin of this solution.
    I don't think you should use this listener if you need a constant one, luckily I need to listen only at specific times.

    Override the 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);
        }
    
    }  
    

    Usage:

    myRecyclerView.setOnScrollStoppedListener(new MyRecyclerView.OnScrollStoppedListener() {
        @Override
        public void onScrollStopped() {
            // Do your thing
        }
    });
    
    myRecyclerView.startScrollerTask();
    
    0 讨论(0)
  • 2021-02-01 04:07

    I've faced the same issue and found a workaround, which is to use the smoothScrollToPosition in layout manager. This method triggers the scroll listener. So basically this is what I use to have:

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

    and now I've changed to this:

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

    and it's working fine for me.

    0 讨论(0)
  • 2021-02-01 04:07

    It's a bit rudimentary, but you could try this Subclass of 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);
        }
    }
    
    0 讨论(0)
  • 2021-02-01 04:09

    To explicitly trigger onScrollListener over recycler view use:

    recyclerView.smoothScrollBy(x, y);
    //x is the horizontal displacement and y is vertical displacement.
    
    0 讨论(0)
提交回复
热议问题