androidandroid-recyclerviewandroid-scrollviewonflingfastscroll

Fast Scrolling on RecyclerView


I would like to enable fling/fast scrolling on the recycler view. What I mean is that if user performs fling motion, the view continues scrolling and starts decelerating (I guess that's called fast scrolling).

I have a RecyclerView in a ScrollView

<ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scroll">

    <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/items"/>

</ScrollView>

I set layout manager to Linear

    RecyclerView itemsView = findViewById(R.id.items);
    stocksView.setLayoutManager(new LinearLayoutManager(this));

I do have a custom adapter attached to the RecyclerView

public abstract class RecyclerAdapter<E>
        extends RecyclerView.Adapter<ItemView>
{
    private ItemTouchHelper touchHelper;

    protected final List<E> items = new ArrayList<>();

    protected RecyclerAdapter()
    {
    }

    @Override
    public void onBindViewHolder(@NonNull final ItemView holder, int position)
    {
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView)
    {
        super.onAttachedToRecyclerView(recyclerView);
        touchHelper = new ItemTouchHelper(new ItemTouchHelperCallback(this));
        touchHelper.attachToRecyclerView(recyclerView);
    }

    @Override
    public int getItemCount()
    {
        return items.size();
    }
}

And my ItemTouchHelperCallback is

public class ItemTouchHelperCallback
        extends ItemTouchHelper.Callback
{
    ItemTouchHelperCallback(RecyclerAdapter adapter)
    {
    }

    @Override
    public boolean isItemViewSwipeEnabled()
    {
        return true;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
    {
        int dragFlags  = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = 0;
        return ItemTouchHelper.Callback.makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target)
    {
        if (source.getItemViewType() != target.getItemViewType())
        {
            return false;
        }

        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int i)
    {
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)
    {
        // We only want the active item to change
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
        {
            // Let the view holder know that this item is being moved or dragged
            ((ItemView) viewHolder).onItemSelected();
        }

        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
    {
        super.clearView(recyclerView, viewHolder);
        // Tell the view holder it's time to restore the idle state\
        ((ItemView) viewHolder).onItemClear();
    }
}

Yet somehow whenever I try to scroll it stops the second I lift my finger. How do I get it to continue trying to scroll.


Solution

  • Remove the ScrollView from your layout, and don't use wrap_content for the RecyclerView's height. RecyclerView already provides scrolling by itself, and you can use whatever layout_ attributes you had on the ScrollView to make the RecyclerView the right size.