danoz73/RecyclerViewFastScroller

Scroll Progress Calculation not smooth

Opened this issue · 1 comments

I didn't test but couldn't this

 @Override
    public float calculateScrollProgress(RecyclerView recyclerView) {
        LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        int lastFullyVisiblePosition = layoutManager.findLastCompletelyVisibleItemPosition();

        View visibleChild = recyclerView.getChildAt(0);
        if (visibleChild == null) {
            return 0;
        }
        ViewHolder holder = recyclerView.getChildViewHolder(visibleChild);
        int itemHeight = holder.itemView.getHeight();
        int recyclerHeight = recyclerView.getHeight();
        int itemsInWindow = recyclerHeight / itemHeight;

        int numItemsInList = recyclerView.getAdapter().getItemCount();
        int numScrollableSectionsInList = numItemsInList - itemsInWindow;
        int indexOfLastFullyVisibleItemInFirstSection = numItemsInList - numScrollableSectionsInList - 1;

        int currentSection = lastFullyVisiblePosition - indexOfLastFullyVisibleItemInFirstSection;

        return (float) currentSection / numScrollableSectionsInList;
    }

be replaced with this?

 public float calculateScrollProgress(RecyclerView recyclerView) {
        float scrollOffset = recyclerView.computeVerticalScrollOffset();
        float scrollRange = recyclerView.computeVerticalScrollRange();
        float scrollExtent = recyclerView.computeVerticalScrollExtent();
        return scrollOffset / (scrollRange - scrollExtent);
    }

I agree with @timothyjc's suggestion, but, in my opinion, it is slightly incorrect: as far as I understand, the "offset" represents the top of visible RecyclerView content and "extent" is the bottom of it (so the size of default scrollbar represents the relative size of currently visible "window" into RecyclerView contents). This means, that accounting for scroll extent makes sense only when slider's size is influenced by it. And quick scroll thumb, that changes it's size on fly, makes for a bad quick scroller.

So in the end it should be more like:

final int thumbTop = recycler.computeVerticalScrollOffset();
final int trackLength = recycler.computeVerticalScrollRange();

if (trackLength <= 0 || thumbTop < 0 || trackLength == thumbTop) {
    // the quick scroll can not be rendered at all
    return -1f;
}

return scrollProgress = thumbTop / (float) trackLength;

This way the top of fixed-size thumb View would correspond exactly to the topmost visible part of RecyclerView contents.