Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advanced RecyclerView library - code examples

https://github.com/h6ah4i/android-advancedrecyclerview

This seems to be a great library in terms of what functionality it offers. However, it lacks good documentation. It has a "tutorial" on Swipeable items, but like some other people I couldn't follow it.

Does anyone have a working example or can anyone make a simple Use Case of swiping an item and showing a button under it using this library? It would be useful for lots of people interested in this functionality.

like image 354
iBobb Avatar asked Mar 21 '16 14:03

iBobb


2 Answers

You can find better detailed documentation in the main website: https://advancedrecyclerview.h6ah4i.com

and the following is copied from the swipeable page in the documentation:


Step 1. Make the adapter supports stable IDs

This step is very important. If adapter does not return stable & unique IDs, that will cause some weird behaviors (wrong animations, NPE, etc...)

class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    MyAdapter() {
        setHasStableIds(true);
    }

    @Override
    public long getItemId(int position) {
        // requires static value, it means need to keep the same value
        // even if the item position has been changed.
        return mItems.get(position).getId();
    }
}

Step 2. Modify layout file of item views

Wrap content views with another FrameLayout whitch has @+id/container ID.

<!-- for itemView -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="56dp">
    <!-- Content View(s) -->
    <TextView
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"/>
</FrameLayout>

⏬ ⏬ ⏬

<!-- for itemView -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="56dp">

    <!-- for getSwipeableContainerView() -->
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Content View(s) -->
        <TextView
            android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"/>

    </FrameLayout>
</FrameLayout>

Step 3. Modify ViewHolder

  1. Change parent class to AbstractSwipeableItemViewHolder.
  2. Implement getSwipeableContainerView() method.

Note: The AbstractSwipeableItemViewHolder class is a convenience class which implements boilerplace methods of `SwipeableItemViewHolder.

class MyAdapter ... {
    static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        MyViewHolder(View v) {
            super(v);
            textView = (TextView) v.findViewById(android.R.id.text1);
        }
    }
    ...
}

⏬ ⏬ ⏬

class MyAdapter ... {
    static class MyViewHolder extends AbstractSwipeableItemViewHolder {
        TextView textView;
        FrameLayout containerView;

        public MyViewHolder(View v) {
            super(v);
            textView = (TextView) v.findViewById(android.R.id.text1);
            containerView = (FrameLayout) v.findViewById(R.id.container);
        }

        @Override
        public View getSwipeableContainerView() {
            return containerView;
        }
    }
}

Step 4. Implement the SwipeableItemAdapter interface

class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    ...
}

⏬ ⏬ ⏬

class MyAdapter
        extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
        implements SwipeableItemAdapter<MyAdapter.MyViewHolder> {

    @Override
    public int onGetSwipeReactionType(MyViewHolder holder, int position, int x, int y) {
        // Make swipeable to LEFT direction
        return Swipeable.REACTION_CAN_SWIPE_LEFT;
    }

    @Override
    public void onSetSwipeBackground(MyViewHolder holder, int position, int type) {
        // You can set background color/resource to holder.itemView.

        // The argument "type" can be one of the followings;
        // - Swipeable.DRAWABLE_SWIPE_NEUTRAL_BACKGROUND
        // - Swipeable.DRAWABLE_SWIPE_LEFT_BACKGROUND
        // (- Swipeable.DRAWABLE_SWIPE_UP_BACKGROUND)
        // (- Swipeable.DRAWABLE_SWIPE_RIGHT_BACKGROUND)
        // (- Swipeable.DRAWABLE_SWIPE_DOWN_BACKGROUND)

        if (type == Swipeable.DRAWABLE_SWIPE_LEFT_BACKGROUND) {
            holder.itemView.setBackgroundColor(Color.YELLOW);
        } else {
            holder.itemView.setBackgroundColor(Color.TRANSPARENT);
        }
    }

    @Override
    public SwipeResultAction onSwipeItem(MyViewHolder holder, int position, int result) {
        // Return sub class of the SwipeResultAction.
        //
        // Available base (abstract) classes are;
        // - SwipeResultActionDefault
        // - SwipeResultActionMoveToSwipedDirection
        // - SwipeResultActionRemoveItem
        // - SwipeResultActionDoNothing

        // The argument "result" can be one of the followings;
        // 
        // - Swipeable.RESULT_CANCELED
        // - Swipeable.RESULT_SWIPED_LEFT
        // (- Swipeable.RESULT_SWIPED_UP)
        // (- Swipeable.RESULT_SWIPED_RIGHT)
        // (- Swipeable.RESULT_SWIPED_DOWN)

        if (result == Swipeable.RESULT_LEFT) {
            return new SwipeResultActionMoveToSwipedDirection() {
                // Optionally, you can override these three methods
                // - void onPerformAction()
                // - void onSlideAnimationEnd()
                // - void onCleanUp()
            };
        } else {
            return new SwipeResultActionDoNothing();
        }
    }
}

Step 5. Modify initialization process of RecyclerView

Put some additional initialization process in your Activity / Fragment.

  1. Instantiate RecyclerViewSwipeManager.
  2. Create a wrapped adapter and set it to RecyclerView.
  3. Attach RecyclerView to RecyclerViewSwipeManager.

void onCreate() {
    ...

    RecyclerView recyclerView = findViewById(R.id.recyclerView);
    MyAdapter adapter = new MyAdapter();

    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
}

⏬ ⏬ ⏬

void onCreate() {
    ...

    RecyclerView recyclerView = findViewById(R.id.recyclerView);
    RecyclerViewSwipeManager swipeManager = new RecyclerViewSwipeManager();

    MyAdapter adapter = new MyAdapter();
    RecyclerView.Adapter wrappedAdapter = swipeManager.createWrappedAdapter(adapter);

    recyclerView.setAdapter(wrappedAdapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    // disable change animations
    ((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

    swipeManager.attachRecyclerView(recyclerView);
}

I hope my answer will help.

like image 66
Zacktamondo Avatar answered Oct 20 '22 06:10

Zacktamondo


I found the library to be well documented and easy to use.

I have picked the code from the original sample that was needed to implement swipe with button underneath which can be found here.

Hopefully following tips will make it even more easier to understand the pattern in which samples are implemented.

Overview

createAdapter method in LauncherPageFragment gives a overview as to which activity contains which feature

Every sample follow either of the the two pattern:

Basic Sample
In case of basic sample the adapter and view holder needed for the recycler view are defined in the same activity class.

Complex Sample
In case of complex sample the adapter and view holder are created separately and the recycler view is itself defined in another fragment.
In such cases there is a additional fragment which is added in activity. These are present in com.h6ah4i.android.example.advrecyclerview.common.fragment package, which is used to provide the data that needs to be displayed in the recycler view.

For the swipe with button you need to create RecyclerViewTouchActionGuardManager (to suppress scrolling while swipe-dismiss animation is running) and RecyclerViewSwipeManager to create a wrapped adapter.

For adapater you will need to implment SwipeableItemAdapter interface and view holder needs to extend AbstractSwipeableItemViewHolder instead of RecyclerView.ViewHolder.

Note: I have changed implementation of onSetSwipeBackground In original sample it set some background on the itemview.
This was not needed in case where the view underneath is to be shown. Also it was causing unnecessary redraws.

like image 37
Anirudha Agashe Avatar answered Oct 20 '22 08:10

Anirudha Agashe