RecyclerView的长按多选功能
主要实现功能
- 长按进入删除模式(使用的android官方提供的actionMode)
- 对点击的item进行标记(对item设置背景色)
- 点击ActionMode上的menu进行点击实现删除选中的item
思路
其实思路很简单,用一个HashSet保存RecyclerView的所点击的item的位置,点击删除后要操作RV中的原数据,再执行RecyclerView的notifyDataSetChanged()方法更新数据便好。
运行截图
初始状态
长按后进入ActionMode
代码
adapter
public class RvAdapter extends RecyclerView.Adapter<RvHolder> {
private List<String> items;
private LayoutInflater inflater;
private Context context;
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public RvAdapter(Context context, List<String> items){
this.items = items;
this.context = context;
inflater = LayoutInflater.from(context);
}
@Override
public RvHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.item,parent,false);
RvHolder holder = new RvHolder(view);
return holder;
}
@Override
public void onBindViewHolder(RvHolder holder, final int position) {
holder.setData(items.get(position),position);
if (onItemClickListener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClick(v,position);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
onItemClickListener.onItemLongClick(v,position);
return false;
}
});
}
}
public void remove(String str){
items.remove(str);
notifyDataSetChanged();
}
public String getItem(int pos){
return items.get(pos);
}
@Override
public int getItemCount() {
return items.size();
}
public interface OnItemClickListener{
void onItemClick(View view, int position);
void onItemLongClick(View view,int position);
}
}
ViewHolder
class RvHolder extends RecyclerView.ViewHolder {
private TextView textView;
public RvHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.tv);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void setData(String item, int position){
Set<Integer> positionSet = MainActivity.instance.positionSet;
if (positionSet.contains(position)) {
itemView.setBackground(MainActivity.instance.getResources().getDrawable(R.drawable.bg_selected));
} else {
itemView.setBackground(MainActivity.instance.getResources().getDrawable(R.drawable.btn_common));
}
textView.setText(item);
}
}
Activity
public class MainActivity extends AppCompatActivity implements ActionMode.Callback {
private ActionMode actionMode;
public Set<Integer> positionSet = new HashSet<>();
private RvAdapter adapter;
public static MainActivity instance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
instance = this;
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
List<String> items = new ArrayList<>();
for (int i=1;i<=20;i++){
items.add("第"+i+"个item");
}
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
adapter = new RvAdapter(this,items);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
recyclerView.setItemAnimator(new DefaultItemAnimator());
adapter.setOnItemClickListener(new RvAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if (actionMode != null) {
// 如果当前处于多选状态,则进入多选状态的逻辑
// 维护当前已选的position
addOrRemove(position);
} else {
// 如果不是多选状态,则进入点击事件的业务逻辑
// TODO something
}
}
@Override
public void onItemLongClick(View view, int position) {
if (actionMode == null) {
actionMode = startSupportActionMode(MainActivity.this);
}
}
});
}
private void addOrRemove(int position) {
if (positionSet.contains(position)) {
// 如果包含,则撤销选择
positionSet.remove(position);
} else {
// 如果不包含,则添加
positionSet.add(position);
}
if (positionSet.size() == 0) {
// 如果没有选中任何的item,则退出多选模式
actionMode.finish();
} else {
// 设置ActionMode标题
actionMode.setTitle(positionSet.size() + " 已选择");
// 更新列表界面,否则无法显示已选的item
adapter.notifyDataSetChanged();
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
if (actionMode == null) {
actionMode = mode;
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_delete, menu);
return true;
} else {
return false;
}
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete:
// 删除已选
Set<String> valueSet = new HashSet<>();
for (int position : positionSet) {
valueSet.add(adapter.getItem(position));
}
for (String val : valueSet) {
adapter.remove(val);
}
mode.finish();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
positionSet.clear();
adapter.notifyDataSetChanged();
}
}
注意
因为博主是个android初学者,这个问题耗费最长时间的地方是解决RV滑动item选中位置显示错位,要在onBindViewHolder中设置每一个item的背景色,否则RV在回收的过程中会将你在点击的时候设置的背景色回收,滑动的时候会造成错乱。
代码地址:
http://download.csdn.net/detail/srtianxia/9369762
https://github.com/srtianxia/RvSelectDemo