Gesture Recycler

This library provides swipe & drag and drop support for RecyclerView. Based on great example from Android-ItemTouchHelper-Demo.

Gesture-Recycler

Features

  • item click/long press/double tap listener
  • background view for swipeable items
  • empty view
  • undo
  • swipe
  • long press drag
  • manual mode drag
  • support for different layout managers
  • predefined drag & swipe flags for RecyclerView's layout managers
  • DiffUtil feature

Dependency

To use this library in your android project, just simply add the following dependency into your build.gradle

dependencies {
    compile 'com.thesurix.gesturerecycler:gesture-recycler:1.5.0'
}

How to use?

// Define your RecyclerView and adapter as usually
final LinearLayoutManager manager = new LinearLayoutManager(getContext());
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(manager);

// Extend GestureAdapter and write your own
// ViewHolder items must extend GestureViewHolder
final MonthsAdapter adapter = new MonthsAdapter(getContext(), R.layout.linear_item);
adapter.setData(getMonths());
recyclerView.setAdapter(adapter);

Swipe and drag & drop support:

GestureManager gestureManager = new GestureManager.Builder(mRecyclerView)
                 // Enable swipe
                .setSwipeEnabled(true)
                 // Enable long press drag and drop 
                .setLongPressDragEnabled(true)
                 // Enable manual drag from the beginning, you need to provide View inside your GestureViewHolder
                .setManualDragEnabled(true)
                 // Use custom gesture flags
                 // Do not use those methods if you want predefined flags for RecyclerView layout manager 
                .setSwipeFlags(ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)
                .setDragFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN)
                .build();

Background view for swipeable items:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Content of the background view (you can use regular layout or ViewStub for better performance)-->
    <ViewStub
            android:id="@+id/background_view_stub"
            android:inflatedId="@+id/background_view"
            android:layout="@layout/background_view_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    <LinearLayout
            android:id="@+id/foreground_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
            <!-- Content of the top view -->
    </LinearLayout>
</FrameLayout>
    // Override getForegroundView(), getBackgroundView() methods in ViewHolder to provide top and bottom view
    @Override
    public View getForegroundView() {
        return mForegroundView; // This view comes from R.id.foreground_view
    }

    @Override
    public View getBackgroundView() {
        return mBackgroundView; // This view comes from R.id.background_view_stub
    }

Data callbacks:

adapter.setDataChangeListener(new GestureAdapter.OnDataChangeListener<MonthItem>() {
            @Override
            public void onItemRemoved(final MonthItem item, final int position) {
            }

            @Override
            public void onItemReorder(final MonthItem item, final int fromPos, final int toPos) {
            }
        });

Data animations:

// Support for data animations
adapter.add(month);
adapter.insert(month, 5);
adapter.remove(5);

// or
adapter.setData(months, diffUtilCallback)

// This will interrupt pending animations
adapter.setData(months)

Item click events:

// Attach DefaultItemClickListener or implement RecyclerItemTouchListener.ItemClickListener
recyclerView.addOnItemTouchListener(new RecyclerItemTouchListener<>(new DefaultItemClickListener<CustomItem>() {
            @Override
            public boolean onItemClick(final CustomItem item, final int position) {
                // return true if the event is consumed
                return false;
            }

            @Override
            public void onItemLongPress(final CustomItem item, final int position) {
            }

            @Override
            public boolean onDoubleTap(final CustomItem item, final int position) {
                // return true if the event is consumed
                return false;
            }
        }));

Empty view:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    
    <!-- Define your empty view in layout -->
    <TextView
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textAppearance="@android:style/TextAppearance.Large"
        android:text="No data"/>
</FrameLayout>
// Pass null to disable empty view
final View emptyView = view.findViewById(R.id.empty_view);
adapter.setEmptyView(emptyView);

Undo:

// Undo last data transaction (add, insert, remove, swipe, reorder)
adapter.undoLast();

// Set undo stack size
adapter.setUndoSize(2);

Help

See examples.

To do

  • kotlin
  • tests?

GitHub