AndroidDeveloperLB / LollipopContactsRecyclerViewFastScroller

A sample of how to mimic the way that the contacts app handles a Fast-Scroller for a RecyclerView
Apache License 2.0
540 stars 95 forks source link

Scrolling RecyclerView, handle is not smooth #3

Closed davideas closed 9 years ago

davideas commented 9 years ago

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.

davideas commented 9 years ago

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);
    }
AndroidDeveloperLB commented 9 years ago

Can you show it in the sample app perhaps?

davideas commented 9 years ago

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:

  1. When handle is arrived at bottom/top there's still some scroll to do.
  2. 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 :-)

AndroidDeveloperLB commented 9 years ago

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.

Rainer-Lang commented 9 years ago

Any news here?

AndroidDeveloperLB commented 9 years ago

@Rainer-Lang No. Otherwise I would have closed this issue. :)

haogefeifei commented 9 years ago

I have some questions,But the demo did not.

AndroidDeveloperLB commented 9 years ago

@haogefeifei I don't understand.

AndroidDeveloperLB commented 9 years ago

anyway issue was fixed by @dimbslmh .

AndroidDeveloperLB commented 8 years ago

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