Android: How to get the current X offset of RecyclerView?

Solution 1:

RecyclerView already have method to get horizontal and vertical scroll offset

mRecyclerView.computeHorizontalScrollOffset()
mRecyclerView.computeVerticalScrollOffset()

This will work for RecyclerViews containing cells of the same height (for vertical scroll offset) and the same width (for horizontal scroll offset)

Solution 2:

enter image description here

Solution 1: setOnScrollListener

Save your X-Position as class variable and update each change within the onScrollListener. Ensure you don't reset overallXScroll (f.e. onScreenRotationChange)

 private int overallXScroll = 0;
 //...
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        overallXScroll = overallXScroll + dx;
        Log.i("check","overall X  = " + overallXScroll);

    }
 });

Solution 2: Calculate current position.

In my case, I have a horizontal List which is filled with time values (0:00, 0:30, 1:00, 1:30 ... 23:00, 23:30). I'm calculating the time from the time-item, which is in the middle of the screen (calculation point). That's why I need the exact X-Scroll Position of my RecycleView

  • Each time item has the same width of 60dp (fyi: 60dp = 30min, 2dp = 1min)
  • First item (Header item) has an extra padding, to set 0min to the center

    private int mScreenWidth = 0;
    private int mHeaderItemWidth = 0;
    private int mCellWidth = 0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      //init recycle views
      //...
      LinearLayoutManager mLLM = (LinearLayoutManager) getLayoutManager();
      DisplayMetrics displaymetrics = new DisplayMetrics();
      this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
      this.mScreenWidth = displaymetrics.widthPixels;
    
      //calculate value on current device
      mCellWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources()
            .getDisplayMetrics());
    
      //get offset of list to the right (gap to the left of the screen from the left side of first item)
      final int mOffset = (this.mScreenWidth / 2) - (mCellWidth / 2);
    
      //HeaderItem width (blue rectangle in graphic)
      mHeaderItemWidth = mOffset + mCellWidth;
    
      mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
    
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
    
            //get first visible item
            View firstVisibleItem = mLLM.findViewByPosition(mLLM.findFirstVisibleItemPosition());
    
            int leftScrollXCalculated = 0;
            if (firstItemPosition == 0){
                   //if first item, get width of headerview (getLeft() < 0, that's why I Use Math.abs())
                leftScrollXCalculated = Math.abs(firstVisibleItem.getLeft());
            }
            else{
    
                   //X-Position = Gap to the right + Number of cells * width - cell offset of current first visible item
                   //(mHeaderItemWidth includes already width of one cell, that's why I have to subtract it again)
                leftScrollXCalculated = (mHeaderItemWidth - mCellWidth) + firstItemPosition  * mCellWidth + firstVisibleItem.getLeft();
            }
    
            Log.i("asdf","calculated X to left = " + leftScrollXCalculated);
    
        }
    });
    

    }

Solution 3:

Thanks to @umar-qureshi for the right lead! It appears that you can determine the scroll percentage with Offset, Extent, and Range such that

percentage = 100 * offset / (range - extent)

For example (to be put in an OnScrollListener):

int offset = recyclerView.computeVerticalScrollOffset();
int extent = recyclerView.computeVerticalScrollExtent();
int range = recyclerView.computeVerticalScrollRange();

int percentage = (int)(100.0 * offset / (float)(range - extent));

Log.i("RecyclerView, "scroll percentage: "+ percentage + "%");