Android开发之RecyclerView的交互动画(实现拖拽和删除)

做RecyclerView做相关的动画效果的时候,用的最多的是v7包下的ItemTouchHelper类,这个类很强大,如有兴趣的童鞋可以自行翻看源码,接下来我带领大家实现RecyclerView相关的交互动画。大家看下面的效果(拖拽和删除):


------------------------------------------华丽的分割线---------------------------------------------------------------------

实现原理:通过重写ItemTouchHelper类的callback回调方法,然后itemTouchHelper.attachToRecyclerView(mRecyclerView)来实现item的拖拽和删除。

------------------------------------------华丽的分割线---------------------------------------------------------------------

首先我们需要先定义一个接口

当拖拽的时候回调和当条目被移除的时候回调(详细看代码注释):

public interface ItemTouchMoveListener {

	/**
	 * 当拖拽的时候回调
	 * 可以在此方法里面实现:拖拽条目并实现刷新效果
	 * fromPosition 从什么位置拖
	 * toPosition	到什么位置
	 * 是否执行了move
	 */
	boolean onItemMove(int fromPosition, int toPosition);

	/**
	 * 当条目被移除是回调
	 * position 移除的位置
	 */
	boolean onItemRemove(int position);
}
接口完成之后开始重写ItemTouchHelper.Callback,来判断用户的动作滑动方向以及选中状态等....

import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.support.v7.widget.helper.ItemTouchHelper.Callback;

public class MyItemTouchHelperCallback extends Callback {
    private ItemTouchMoveListener moveListener;

    public MyItemTouchHelperCallback(ItemTouchMoveListener moveListener) {
        this.moveListener = moveListener;
    }

    //Callback回调监听时先调用的,用来判断当前是什么动作,比如判断方向(意思就是我要监听哪个方向的拖动)
    @Override
    public int getMovementFlags(RecyclerView recyclerView, ViewHolder holder) {
   
        //需要监听的拖拽方向是哪两个方向
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //我要监听的swipe侧滑方向是哪个方向
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int flags = makeMovementFlags(dragFlags, swipeFlags);
        return flags;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        // 是否允许长按拖拽效果
        return true;
    }

    //当移动的时候回调的方法--拖拽
    @Override
    public boolean onMove(RecyclerView recyclerView, ViewHolder srcHolder, ViewHolder targetHolder) {
        if (srcHolder.getItemViewType() != targetHolder.getItemViewType()) {
            return false;
        }
        // 在拖拽的过程当中不断地调用adapter.notifyItemMoved(from,to);
        boolean result = moveListener.onItemMove(srcHolder.getAdapterPosition(), targetHolder.getAdapterPosition());
        return result;
    }

    //侧滑的时候回调的
    @Override
    public void onSwiped(ViewHolder holder, int arg1) {
        // 监听侧滑,1.删除数据;2.调用adapter.notifyItemRemove(position)
        moveListener.onItemRemove(holder.getAdapterPosition());
    }


    @Override
    public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
        //判断选中状态
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(R.color.colorAccent));
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
        // 恢复
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
        super.clearView(recyclerView, viewHolder);
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView,
                            ViewHolder viewHolder, float dX, float dY, int actionState,
                            boolean isCurrentlyActive) {
        //dX:水平方向移动的增量(负:往左;正:往右)范围:0~View.getWidth  0~1
        float alpha = 1 - Math.abs(dX) / viewHolder.itemView.getWidth();
        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            //透明度动画
            viewHolder.itemView.setAlpha(alpha);//1~0
            viewHolder.itemView.setScaleX(alpha);//1~0
            viewHolder.itemView.setScaleY(alpha);//1~0
        }

        //删掉一个条目之后,恢复原状
        if (alpha == 0) {
            viewHolder.itemView.setAlpha(1);//1~0
            viewHolder.itemView.setScaleX(1);//1~0
            viewHolder.itemView.setScaleY(1);//1~0
        }

        //此super方法会自动处理setTranslation
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }

}

接下来还需要个接口该接口主要是回调拖拽效果的

import android.support.v7.widget.RecyclerView.ViewHolder;

public interface StartDragListener {
	/**
	 * 该接口用于需要主动回调拖拽效果的
	 * @param viewHolder
	 */
	void onStartDrag(ViewHolder viewHolder);}
然后在mainactivity中实现StartDragListener接口,传递给adapter,同时在实现的接口里设置itemTouchHelper.startDrag(viewHolder);

mainactivy完整代码:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements StartDragListener {

    private RecyclerView mRecyclerView;
    private ArrayList<String> mList;
    private MyAdapter mAdapter;
    private ItemTouchHelper itemTouchHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        mAdapter = new MyAdapter(getData(), this);
        mRecyclerView.setAdapter(mAdapter);

        //条目触摸帮助类
        ItemTouchHelper.Callback callback = new MyItemTouchHelperCallback(mAdapter);
        itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);
    }

    @Override
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
        itemTouchHelper.startDrag(viewHolder);
    }

    public List<String> getData() {
        mList = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
            mList.add("item" + i);
        }
        return mList;
    }
}

然后在Adapter中实现数据的交换刷新和移除。

MyAdapter完整代码:

import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Collections;
import java.util.List;

public class MyAdapter extends Adapter<MyAdapter.MyViewHolder> implements ItemTouchMoveListener {
    private List<String> mList;
    private StartDragListener mDragListener;

    public MyAdapter(List<String> list, StartDragListener dragListener) {
        this.mList = list;
        this.mDragListener = dragListener;
    }

    class MyViewHolder extends ViewHolder {

        private ImageView iv;
        private TextView tv;


        public MyViewHolder(View itemView) {
            super(itemView);
            iv = (ImageView) itemView.findViewById(R.id.iv);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }

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

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int location) {
        holder.tv.setText(mList.get(location));

        holder.iv.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    //传递触摸情况给谁?
                    mDragListener.onStartDrag(holder);
                }
                return false;
            }
        });
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        // 1.数据交换;2.刷新
        Collections.swap(mList, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
        return true;
    }

    @Override
    public boolean onItemRemove(int position) {
        mList.remove(position);
        notifyItemRemoved(position);
        return true;
    }
}

两个简单布局一并贴出:

mainActivity布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.fly.rv03.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
item布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="text" />
    </LinearLayout>
</LinearLayout>


------------------------------------------ 华丽的分割线---------------------------------------------------------------------

再次体验下效果:

长按移动:

------------------------------ 华丽的分割线-------------------------------------------------------------------------------


RecyclerView先暂时告一段落,下节课我们学习另外一个知识点,敬请期待。。。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等待着冬天的风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值