Android: How to get the current X offset of RecyclerView?
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 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;@Overrideprotected 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); }});
}
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 + "%");