Android – swipe to close the recyclerview with animation on the background

According to my understanding, one possibility to realize the sliding to release of recyclerview using the background under the swipe project (as in many Google Applications) is to implement a simple callback of itemtouchhelper and draw the background in the method onchilddraw

This is my implementation:

itemtouchhelper.SimpleCallback simpleItemTouchCallback = new itemtouchhelper.SimpleCallback(0, itemtouchhelper.RIGHT) {
    // create objects once and avoid allocating them in the onChildDraw method
    Drawable background;
    Drawable icon;
    int iconMargin;
    boolean initialized;

    private void init() {
        background = new ColorDrawable(Color.RED);
        icon = ContextCompat.getDrawable(mAppContext, R.drawable.ic_delete_white_24dp);
        iconMargin = (int) mAppContext.getResources().getDimension(R.dimen.fab_margin);
        initialized = true;
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
        // remove swiped item from the list and notify the adapter
        int position = viewHolder.getAdapterPosition();
        mItemList.remove(position);
        mRecyclerViewAdapter.notifyDataSetChanged();
    }

    @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) {
            if (dX > 0) {
                View itemView = viewHolder.itemView;
                // if viewHolder has been swiped away, don't do anything
                if (viewHolder.getAdapterPosition() == -1) {
                    return;
                }
                if (!initialized) {
                    init();
                }
                // draw background
                int dXSwipe = (int) (dX * 1.05); // increase slightly dX to avoid view flickering, compensating loss of precision due to int conversion 
                background.setBounds(itemView.getLeft(), itemView.getTop(),
                itemView.getLeft() + dXSwipe, itemView.getBottom());
                background.draw(c);
                // draw icon
                int top = (itemView.getTop() + itemView.getBottom() - icon.getIntrinsicHeight()) / 2;
                int left = itemView.getLeft() + iconMargin;
                icon.setBounds(left, top, left + icon.getIntrinsicWidth(), top + icon.getIntrinsicHeight());
                icon.draw(c);
            }
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        }
    };
    itemtouchhelper itemtouchhelper = new itemtouchhelper(simpleItemTouchCallback);
    itemtouchhelper.attachToRecyclerView(mRecyclerView);

Now, the question is how to animate the view in the following background. An example of this animation can be obtained from Google Calendar: when sliding an event or reminder, the icon on the left will be enlarged according to the horizontal displacement

Who knows how to achieve this goal? Is it necessary to adopt different methods? There may be two views in the viewholder. As proposed here, recyclerview swipe with a view below it?

resolvent:

I found out how to do it

For those interested, the solution is to use two views (foreground and background) and animate the background during sliding

Layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="wrap_content"
    android:background="@color/item_delete_background">

    <ImageView
        android:id="@+id/item_delete_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="@dimen/fab_margin"
        android:layout_marginStart="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_delete_white_24dp" />

    <android.support.constraint.ConstraintLayout
        android:id="@+id/item_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/gray_bg">

        <!--recyclerview item layout-->

    </android.support.constraint.ConstraintLayout>

</FrameLayout>

Opinion holder:

class MyViewHolder extends RecyclerView.ViewHolder {
    private ConstraintLayout mItemLayout;
    private ImageView mItemDeleteIcon;

    MyViewHolder(View v) {
        super(v);
        mItemLayout = (ConstraintLayout) v.findViewById(R.id.item_layout);
        mEventDeleteIcon = (ImageView) v.findViewById(R.id.item_delete_icon);
    }

    View getViewToSwipe() {
        return mItemLayout;
    }

    View getViewToAnimate() {
        return mItemDeleteIcon;
    }
}

And itemtouchhelper callbacks:

itemtouchhelper.SimpleCallback mItemTouchCallback = new itemtouchhelper.SimpleCallback(0, itemtouchhelper.RIGHT) {

    // override methods

    public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                                float dX, float dY,
                                int actionState, boolean isCurrentlyActive) {
        // get the view which is currently swiped
        ConstraintLayout itemLayout = (ConstraintLayout) ((MyViewHolder) viewHolder).getViewToSwipe();
        // calculate relative horizontal displacement
        // with proportion dXRelative : 1 = dX : (layoutWidth / 3)
        float dXRelative = dX / itemLayout.getWidth() * 3;
        // check size boundaries
        if (dXRelative > 1) {
            dXRelative = 1;
        }
        if (dXRelative < 0) {
            dXRelative = 0;
        }
        // animate the icon with scaling on both dimensions
        ((MyViewHolder) viewHolder).getViewToAnimate().animate().scaleX(dXRelative).scaleY(dXRelative).setDuration(0).start();
        // call draw over
        getDefaultUIUtil().onDrawOver(c, recyclerView, ((MyViewHolder) viewHolder).getViewToSwipe(), dX, dY, actionState, isCurrentlyActive);
    }
};

After this post, the implementation of the basic behavior (foreground / background in the view holder) is completed: use itemtouchhelper for swing to miss with other view displayed behind the swiped out

I hope it may be useful to sb

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>