Android: How to get current X offset for RecyclerView?

I use Scrollview for the infinite "Timer Carousel" and found out that this is not the best approach ( last question )

Now I have found Recycler View , but I can’t get the current scroll offset in the X direction of the recyclerView ? (Let’s say that each element has a width of 100 pixels, and the second is only 50% wide, so the scroll offset is 150 pixels)

  • all elements have the same width, but therer is some space before the first, after the last element
  • recyclerView.getScrollX() returns 0 (say: initial scroll value)
  • LayoutManager has findFirstVisibleItemPosition , but I cannot calculate the X offset with this

UPDATE

I just found a way to track the X-Position by updating the value with the onScrolled , but I would rather get the actual value, rather than keep track of it all the time!

 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","overallXScroll->" + overallXScroll); } }); 
+43
android scroll position android-recyclerview
Dec 16 '14 at 15:10
source share
5 answers

enter image description here

Solution 1: setOnScrollListener

Save the X-Position variable as a class variable and update each change in onScrollListener . Make sure you do not reset overallXScroll (fe 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 your current position.

In my case, I have a horizontal list that is populated with time values ​​(0:00, 0:30, 1:00, 1:30 ... 23:00, 23:30). I calculate the time from the point in time that is in the middle of the screen (calculation point). That's why I need the exact X-Scroll position of my RecycleView

  • Each time element has the same width of 60dp (fyi: 60dp = 30min, 2dp = 1min)
  • The first element (header element) has an additional addition 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 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 why I have to subtract it again) leftScrollXCalculated = (mHeaderItemWidth - mCellWidth) + firstItemPosition * mCellWidth + firstVisibleItem.getLeft(); } Log.i("asdf","calculated X to left = " + leftScrollXCalculated); } }); 

    }

+39
Dec 18 '14 at 12:01
source share

RecyclerView already has a way to get horizontal and vertical scroll offset

 mRecyclerView.computeHorizontalScrollOffset() mRecyclerView.computeVerticalScrollOffset() 

This will work for RecyclerViews containing cells with the same height (for a vertical scroll shift) and the same width (for a horizontal scroll shift)

+43
Sep 30 '15 at 9:55
source share

Thanks @ umar-qureshi for the right leader! Apparently you can determine the percentage of scroll using Offset , Extent and Range so that

 percentage = 100 * offset / (range - extent) 

For example (to host 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 + "%"); 
+20
May 08 '16 at 2:11
source share
 public class CustomRecyclerView extends RecyclerView { public CustomRecyclerView(Context context) { super(context); } public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public int getHorizontalOffset() { return super.computeHorizontalScrollOffset(); } } 

What you need to get the offset:

 recyclerView.getHorizontalOffset() 
+8
Feb 20 '15 at 22:48
source share

by overriding RecyclerView onScrolled(int dx,int dy) , you can get the scroll offset. but when you add or remove an item, the value may be incorrect.

 public class TempRecyclerView extends RecyclerView { private int offsetX = 0; private int offsetY = 0; public TempRecyclerView(Context context) { super(context); } public TempRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public TempRecyclerView(Context context, @Nullable AttributeSet attrs,int defStyle){ super(context, attrs, defStyle); } /** * Called when the scroll position of this RecyclerView changes. Subclasses should usethis method to respond to scrolling within the adapter data set instead of an explicit listener. * <p>This method will always be invoked before listeners. If a subclass needs to perform any additional upkeep or bookkeeping after scrolling but before listeners run, this is a good place to do so.</p> */ @Override public void onScrolled(int dx, int dy) { // super.onScrolled(dx, dy); offsetX+=dx; offsetY+=dy; } } 
0
Dec 29 '17 at 13:39 on
source share



All Articles