Scrolling RecyclerView, handle is not smooth
Closed this issue · 10 comments
Scrolling normally on the RecyclerView, the Handle is not moving until the next item is reached and so it changes position suddenly: basically the movement is not linear.
This effect is more visible with few elements while with a lot of elements it might be considered acceptable, even if it is not nice to have/see.
So I've reviewed the code.
Now IMO, it is much much better, scrolling RecyclerView is smooth in all cases!
In my code there's a bug with high numbers, proportion is still not ok (should be smaller than now), so I had to add a new factor, called C, in the calculation (experimented while watching that proportion was too big, but now it is a bit too big with high numbers).
Also it's critic the calculation when the difference (itemCount - visibleRange) is 1 or less.
I removed all the old calculation. Now I use dy (delta y) and I put it in the calculation with the new proportion. Please have a look and let me know, this is the new code that should be fixed however:
@Override
public void onScrolled(RecyclerView rv, int dx, int dy) {
//Only react on scroll events when not done by moving the handle by touch
// prevents nervous jumping of the handle
if (handle.isSelected()) return;
float itemCount = recyclerView.getAdapter().getItemCount();
float visibleRange = recyclerView.getChildCount();
// Log.d(TAG, "------------------------");
// Log.d(TAG, "onScrolled itemCount=" + itemCount);
// Log.d(TAG, "onScrolled visibleRange=" + visibleRange);
// Log.d(TAG, "onScrolled dy=" + dy);
//This decreases the proportion to adjust the final multiplication with dy.
float c = itemCount / visibleRange;
// Log.d(TAG, "onScrolled factor c=" + c);
//Subtracting visibleRange value: these items must removed from calculation
// (increase proportion and scroll faster with few items)
float proportion = (itemCount - visibleRange < 1) ? height :
visibleRange / (itemCount - visibleRange + c);
// Log.d(TAG, "onScrolled proportion=" + proportion);
float y = handle.getY() + dy * proportion;
//dy could be bigger then necessary (due to fling) fix min and max value
if (y < 0) y = 0;
else if (y > height - handle.getHeight())
y = height - handle.getHeight();
// Log.d(TAG, "onScrolled Y=" + y);
handle.setY(y);
}
Can you show it in the sample app perhaps?
I tried with 15 elements. With your code:
https://www.dropbox.com/s/ggs4fh6mxamdl1i/capture_Fri_Jul_17_19.32.00.mkv?dl=0
With my code handle movement is now smooth during the scroll, it takes the "delta y":
https://www.dropbox.com/s/7fle9f4eb2xldwh/capture_Fri_Jul_17_19.30.00.mkv?dl=0
But there are 2 bugs, code needs improvements:
- When handle is arrived at bottom/top there's still some scroll to do.
- When handle is dragged and released, position is not relative to the effective position Y. Especially visible if you scroll the RecyclerView again: handle can't move because scroll is finished (hande got different Y caused by manual drag).
I hope it's clear my explanation and videos as well.
I really would like this library works well :-)
oh, it's not that bad. This reminds of what happens to the normal fast-scroller of a ListView, where you choose "setSmoothScrollbarEnabled(false)" :
http://developer.android.com/reference/android/widget/AbsListView.html#setSmoothScrollbarEnabled(boolean)
I hope to see how to fix it too.
Any news here?
@Rainer-Lang No. Otherwise I would have closed this issue. :)
I have some questions,But the demo did not.
@haogefeifei I don't understand.
anyway issue was fixed by @dimbslmh .
I'm not sure, but it might be that adding decorators ruin the fast-scroller, as they can appear and cause computeVerticalScrollOffset and computeVerticalScrollRange jump to different values.
I've found it when adding this library : https://github.com/eowise/recyclerview-stickyheaders