RecyclerView的深入——ItemTouchHelper,实现侧滑删除和上下拖动交换位置
参考文献:https://blog.csdn.net/a553181867/article/details/54799391 (侵删)
今天在总结5.0与6.0新控件的时候发现了这个新的工具类,ItemTouchHelper,这个实现recyclerview侧滑删除与上下拖动交换位置的官方sdk,对此产生浓厚兴趣,于是开始学习了一下,首先来介绍一下ItemTouchHelper这个工具类,它包含了一下几种方法:
getMovementFlags 这个方法返回一个int值用于判断item是上下拖动还是侧滑删除,一般我们使用makeMovementFlags(int,int)或者makeFlag(int,int)来设置;
onMove 这个方法内设置当item移动的时候执行的操作,在里面执行移动方法,用于调换两个viewholder,设置移动的时候返回为true;
onSwiped 这个方法内执行当item打到删除条件的时候的方法;
isLongPressDragEnabled 这个方法设置是否长按触发拖动item,默认为true;
isItemViewSwipeEnabled 这个方法设置左右移动的时候调用onswiped方法,进行item的删除操作,默认返回true;
onSelectedChanged 当item由静止变为拖动状态时调用的方法,其中的actionState参数表示当前的item状态;
这个方法我引用原文章的文献,因为我没有使用过这个方法,理解不深,不敢随便乱说,以后实践过后再来改动
onChildDraw 从方法名字可以看出是item产生变化时的动画效果
这里我在原文基础上加一个onChildDrawOver方法,这个方法在页面变化状态完成之后产生的动画效果
介绍完这些,我们先看看效果图:
接下来上代码:
package com.example.administrator.recycleritemtouchhelper; import android.graphics.Canvas; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private List<String> list = new ArrayList<>(); private String[] item_data = {"111", "222", "333"}; private ItemTouchHelper itemTouchHelper; private ItemTouchHelper.Callback callback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for (int i = 0; i < item_data.length; i++) { list.add(item_data[i]); } recyclerView = findViewById(R.id.recycler_mian); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(linearLayoutManager); final MainAdapter mainAdapter = new MainAdapter(); recyclerView.setAdapter(mainAdapter); callback = new ItemTouchHelper.Callback() { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int move = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int delete = ItemTouchHelper.LEFT; return makeMovementFlags(move, delete); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { mainAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mainAdapter.onItemDelete(viewHolder.getAdapterPosition()); } }; itemTouchHelper = new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recyclerView); } private class MainAdapter extends RecyclerView.Adapter<MainViewHolder> implements ItemTouchHelperAdapter { @NonNull @Override public MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false); return new MainViewHolder(view); } @Override public void onBindViewHolder(@NonNull MainViewHolder holder, int position) { holder.setData(list.get(position)); } @Override public int getItemCount() { return list.size(); } @Override public void onItemMove(int startposition, int endposition) { Collections.swap(list, startposition, endposition); notifyItemMoved(startposition, endposition); } @Override public void onItemDelete(int position) { list.remove(position); notifyItemRemoved(position); } } private class MainViewHolder extends RecyclerView.ViewHolder { private TextView textView; public MainViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.ietm_text); } private void setData(String data) { textView.setText(data); } } public interface ItemTouchHelperAdapter { void onItemMove(int startposition, int endposition); void onItemDelete(int position); } }
现在来分析代码,ItemTouchHelper执行的移动和删除操作,其实就是Adapter里面的notifyItemMoved和notyfyItemRemoved方法,但是我们需要在ItemTouchHelper.CallBack中用到,所以我们将这两个方法在Adapter中写成单独的移动和移除方法:
public interface ItemTouchHelperAdapter { void onItemMove(int startposition, int endposition); void onItemDelete(int position); }
然后在Adapter中引入这个方法,在方法中设置item的移除与移动操作:
@Override public void onItemMove(int startposition, int endposition) { Collections.swap(list, startposition, endposition); notifyItemMoved(startposition, endposition); } @Override public void onItemDelete(int position) { list.remove(position); notifyItemRemoved(position); }
然后我们在onCreat方法中初始化ItemToucherHelper和ItemTouchHelper.callback,并且重写callback中的三个基础方法:
callback = new ItemTouchHelper.Callback() { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int move = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int delete = ItemTouchHelper.LEFT; return makeMovementFlags(move, delete); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { mainAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mainAdapter.onItemDelete(viewHolder.getAdapterPosition()); } };
然后绑定callback和recyclerview:
itemTouchHelper = new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recyclerView);
就可以实现上面的功能啦!
这里要说一下,如果item侧滑删除过程中item超过了百分之五十的位置时离开触摸状态item会自动调用onswipe方法,如果没有的话会自动返回当前位置哦~
我是分割线---------------------------------------------------------------------------------------------------------------------
这里要说一下ItemMove中的Collections类,这个是集合工具类,这里的swep方法是将两个下标的子项交换,其余方法如下:
Collections.shuffle(List<?> list);//随机置换
Collections.sort(List<?> list,Comparator<? super T> c);//排序,可升序可降序
Collections.fill(List<? super ?>list, T object);//替换
Collections.min(List<?>list);//取最小值
Collections.max(List<?>list);//取最大值
Collections.reverse(List<?>list);//将数组反转
Collections.reverse(List<?>list,List<?>list1);//复制
还有可以通过synchronizedCollection方法获得线程安全的集合