Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView ItemTouchHelper - Custom View

I am trying to have a custom view (or image) appear when swiping left/right.

I'm close to having it working, however I'm having issues with using a custom image.

The effect I'm going for is similar to this: RecyclerView ItemTouchHelper swipe remove animation

See what's happening below. It's warping the image as the swipe happens:

enter image description here

Below is what my code looks like:

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
        float dX, float dY, int actionState, boolean isCurrentlyActive) {
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        View itemView = viewHolder.itemView;

        Paint p = new Paint();
        if (dX > 0) {
            Drawable d = ContextCompat.getDrawable(getActivity(), R.drawable.test_check);
            d.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
            d.draw(c);

            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        } 

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}

How can I keep the image static while continuing to draw the background color? Is it possible to even use an Android view instead of an image? Similar to this: https://github.com/wdullaer/SwipeActionAdapter

like image 720
aherrick Avatar asked Aug 02 '15 23:08

aherrick


People also ask

How to attach itemtouchhelper to a recyclerview in Android?

Creates an ItemTouchHelper that will work with the given Callback. You can attach ItemTouchHelper to a RecyclerView via attachToRecyclerView (RecyclerView). Upon attaching, it will add an item decoration, an onItemTouchListener and a Child attach / detach listener to the RecyclerView.

What is recyclerview itemdecoration in Android?

Apart from listed data, RecyclerView has some crucial decorative elements, such as scroll bars and dividers between items. And that’s where RecyclerView.ItemDecoration can help us draw all of the elements without having to spawn any unnecessary Views while we render items and screens.

How to add an itemdecoration instance to recyclerview?

There are two methods you can use to add an ItemDecoration instance to RecyclerView: All added instances of RecyclerView.ItemDecoration are put in a single list and drawn simultaneously.

What can I do with recyclerview?

I’ll show you what it’s capable of and how to implement it when rendering a list. Apart from listed data, RecyclerView has some crucial decorative elements, such as scroll bars and dividers between items.


1 Answers

You can prepare your recycler view item layout to include the check symbol ImageView and maybe another blank view with just the background color. You should also move all the swipeable content into a nested layout. Assign a reference to the swipeable content in your view holder. Then just call setTranslationX on your swipeable content in onChildDraw, like:

((MyViewHolder) viewHolder).swipeableContent.setTranslationX(dX);

Update With Source Code Example:

Recycler view item layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="@dimen/recycler_view_item_height"
    android:background="@color/transparent">

    <!-- background color view -->
    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/purple" />

    <!-- check symbol image view -->
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="@dimen/check_symbol_width"
        android:contentDescription="@null"
        android:src="@drawable/check_symbol" />

    <!-- swipeable content container -->
    <LinearLayout
        android:id="@+id/swipeable_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <!-- here goes your swipeable content -->
    </LinearLayout>

</RelativeLayout>

View holder class:

class MyViewHolder extends RecyclerView.ViewHolder {

    // Swipeable content container.
    LinearLayout swipeableContent;

    /*
     ... here goes other sub-views
    */

    public ExpenseViewHolder(final View itemView) {
        super(itemView);
        // bind swipeable content container view
        swipeableContent = (LinearLayout) itemView.findViewById(R.id.swipeable_content);

        /*
         ... bind other sub-views
        */
    }
}

ItemTouchHelper.Callback subclass:

class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

    @Override
    public void onChildDraw(final Canvas c,
                            final RecyclerView recyclerView,
                            final RecyclerView.ViewHolder viewHolder,
                            final float dX,
                            final float dY,
                            final int actionState,
                            final boolean isCurrentlyActive) {
        if (viewHolder instanceof MyViewHolder) {
            // translate by swipe amount, 
            // the check symbol and the background will stay in place
            ((MyViewHolder) viewHolder).swipeableContent.setTranslationX(dX);
        }
    }

}
like image 101
KuKaBi Avatar answered Oct 13 '22 02:10

KuKaBi