RecycleView實現長按多選全選刪除功能
阿新 • • 發佈:2018-11-22
一、功能:
recycleView橫向列表,實現item新增,長按選擇,全選,全不選的刪除,滑動刪除功能。
用realm構建資料庫儲存列表資料。用FloatingActionButton 作為新增按鈕。
思路:
activity頁面最下面新增一個帶有刪除tab的view,當長按item的時候,view顯示出來。
adapter的itemview裡面,帶有一個checkbox,長按item的時候,checkbox顯示出來。
adapter裡面新增一個是否刪除模式的boolen型判斷物件inDeletionMode,和一個Set<Users> selectedUsers被選中刪除列表。
長按item的時候,inDeletionMode設定為true,並且notifydatasetChanged,更新Bindviewholder的檢視,讓checkbox顯示出來,
刪除模式的時候,checkbox為true的時候,將該位置的user新增到設selectedUsers裡面。
點選全選、全不選的時候,更新adapter裡面的selectedUsers物件,並且更新檢視顯示。
realm的使用參考:realm詳解
效果圖:
二、實現
1、activity
xml:
<?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="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> <android.support.design.widget.FloatingActionButton android:id="@+id/btn_floating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_gravity="right|bottom" android:layout_margin="16dp" android:src="@mipmap/add_user" android:backgroundTint="@color/light_gray" app:rippleColor="@color/login_line_color"/> <LinearLayout android:id="@+id/ll_delete" android:layout_width="match_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" android:background="@color/white" android:gravity="center" android:orientation="vertical" android:visibility="gone"> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="@color/color_text_hint"/> <com.landicorp.dependencelibrary.widget.TabView android:id="@+id/tab_delete" android:layout_width="40dp" android:layout_height="wrap_content" android:paddingBottom="16dp" app:color="@color/color_text_normal" app:icon="@mipmap/delete" app:text="刪除" app:text_size="12sp"/> </LinearLayout> </RelativeLayout>
activity:
/** * 使用者列表,可長按刪除,滑動刪除,新增使用者 */ public class VIPActivity extends BusinessActivity implements View.OnClickListener, UserAdapter.onItemClickListener { private RecyclerView recyclerView; private FloatingActionButton btnFloating; private TabView tabDelete; private LinearLayout llDelete; private RealmResults<Users> usersList; private UserAdapter adapter; Realm realm; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_vip); realm = Realm.getDefaultInstance(); initView(); setTitle("VIP列表"); //全選按鈕設定監聽 getRlTextAheadView().setOnClickListener(this); } //初始化view,recycleView新增介面卡,繫結ItemTouchHelper private void initView() { usersList = realm.where(Users.class).findAll(); adapter = new UserAdapter(); adapter.setUsersList(usersList); adapter.setListener(this); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); btnFloating = (FloatingActionButton) findViewById(R.id.btn_floating); tabDelete = (TabView) findViewById(R.id.tab_delete); llDelete = (LinearLayout) findViewById(R.id.ll_delete); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); recyclerView.setAdapter(adapter); //將touchhelper和recycleview繫結,實現滑動刪除,但是不能實現上下拖拽item,因為realm不支援Collection.swap方式 //這裡自定義了一個callback實現了ItemTouchHelper.Callback介面方法,傳入adapter物件相應滑動刪除事件 ItemTouchHelper.Callback callback = new MyItemHelpCallBack(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView); btnFloating.setOnClickListener(this); tabDelete.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_floating: addUser(); break; case R.id.tab_delete: if (llDelete.isShown()) { deleteUsers(); hideAhead(); llDelete.setVisibility(View.GONE); btnFloating.setVisibility(View.VISIBLE); adapter.setInDeletionMode(false); } break; case R.id.rl_head_text: seletAllOrNot(); break; default: break; } } //新增物件 public void addUser() { DialogUtils.showAddUserDialog(this, "新增使用者", new AddUserDialog.onAddUserListener() { @Override public void addUser(String name, String cardNo) { realm.beginTransaction(); Users user = realm.createObject(Users.class); user.setName(name); user.setCardNo(cardNo); realm.commitTransaction(); } }); } //刪除選中物件 public void deleteUsers() { Set<Users> selectSet = adapter.getSelectSet(); realm.beginTransaction(); Iterator<Users> iterator = selectSet.iterator(); while (iterator.hasNext()) { Users user = iterator.next(); if (usersList.contains(user)) { user.deleteFromRealm(); } } realm.commitTransaction(); } //點選全選,全不選,狀態切換 private void seletAllOrNot() { if (adapter.getSelectSet().size() < usersList.size()) { Set<Users> selectSet = adapter.getSelectSet(); for (int i = 0; i < usersList.size(); i++) { selectSet.add(usersList.get(i)); } adapter.setSelectSet(selectSet); adapter.notifyDataSetChanged(); setAheadText("全不選"); } else { adapter.setSelectSet(new HashSet<Users>()); adapter.notifyDataSetChanged(); setAheadText("全選"); } } @Override public void onItemClick(final Users user) { //listitem 點選事件 } //長按item,隱藏floatingbtn,顯示全選按鈕, //通知adapter變為刪除選擇模式,將當前選中的item的checkbox設定為true @Override public void onItemLongCick(Users user) { if (!llDelete.isShown()) { showTextAhead(); setAheadText("全選"); llDelete.setVisibility(View.VISIBLE); btnFloating.setVisibility(View.GONE); Set<Users> selectSet = new HashSet<>(); selectSet.add(user); adapter.setSelectSet(selectSet); adapter.setInDeletionMode(true); } } //滑動刪除item @Override public void onSwipeToDeleteUser(int position) { if (usersList.size() >= position) { realm.beginTransaction(); usersList.get(position).deleteFromRealm(); realm.commitTransaction(); adapter.notifyDataSetChanged(); } } //activity監聽到adapter選擇了全部的item,全選變成全不選 @Override public void selectedAll() { setAheadText("全不選"); } //點選返回按鈕,如果是刪除狀態,取消刪除 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (llDelete.isShown()) { llDelete.setVisibility(View.GONE); btnFloating.setVisibility(View.VISIBLE); hideAhead(); adapter.setInDeletionMode(false); return true; } return super.onKeyDown(keyCode, event); } //關閉realm,防止記憶體洩漏 @Override protected void onDestroy() { super.onDestroy(); realm.close(); } }
2、adapter
item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="3">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.8"
android:gravity="center_vertical"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="姓名:"
android:textColor="@color/color_text_normal"
android:textSize="14sp"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/color_text_normal"
android:textSize="14sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.2"
android:paddingLeft="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="卡號:"
android:textColor="@color/color_text_hint"
android:textSize="12sp"/>
<TextView
android:id="@+id/tv_cardNo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/color_text_hint"
android:textSize="12sp"/>
</LinearLayout>
</LinearLayout>
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:visibility="gone"/>
</RelativeLayout>
adapter:
/**
* 使用者列表介面卡
*/
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> implements View.OnClickListener
, View.OnLongClickListener {
private RealmResults<Users> usersList;
private onItemClickListener listener;
//設定顯示的資料
public void setUsersList(RealmResults<Users> usersList) {
this.usersList = usersList;
}
//設定監聽器
public void setListener(onItemClickListener listener) {
this.listener = listener;
}
//是否刪除模式
private boolean inDeletionMode = false;
//設定是否為刪除模式,改變繫結檢視
public void setInDeletionMode(boolean inDeletionMode) {
this.inDeletionMode = inDeletionMode;
notifyDataSetChanged();
}
//選中要刪除使用者
private Set<Users> selectSet = new HashSet<>();
/**
* 獲取選中要刪除的列表
*
* @return
*/
public Set<Users> getSelectSet() {
return selectSet;
}
public void setSelectSet(Set<Users> selectSet) {
this.selectSet = selectSet;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
//這裡呼叫realm的isValid方法,判斷當前資料是否可用,防止出現數據被刪除仍然使用導致崩潰
if (usersList.get(position).isValid()) {
holder.tvName.setText(usersList.get(position).getName());
holder.tvCardNo.setText(usersList.get(position).getCardNo());
//刪除模式,checkbox顯示,否則不顯示
holder.checkbox.setVisibility(inDeletionMode ? View.VISIBLE : View.GONE);
if (inDeletionMode) {
holder.rootView.setOnClickListener(null);
holder.rootView.setOnLongClickListener(null);
//設定當前item的checkbox是否為選中狀態
//item長按刪除的時候,activity設定了當前長按的item物件儲存在selectset裡面了
holder.checkbox.setChecked(selectSet.contains(usersList.get(position)));
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
selectSet.add(usersList.get(position));
} else {
selectSet.remove(usersList.get(position));
}
//全部選中,通知activity “全選” 變成 “全不選”
if (selectSet.size() == usersList.size()) {
listener.selectedAll();
}
}
});
} else {
holder.checkbox.setOnCheckedChangeListener(null);
holder.rootView.setOnClickListener(this);
holder.rootView.setOnLongClickListener(this);
}
holder.itemView.setTag(usersList.get(position));
}
}
@Override
public int getItemCount() {
return usersList.size();
}
@Override
public void onClick(View v) {
Users user = (Users) v.getTag();
if (null != user && listener != null) {
listener.onItemClick(user);
}
}
@Override
public boolean onLongClick(View v) {
Users user = (Users) v.getTag();
if (null != user && listener != null) {
listener.onItemLongCick(user);
}
return true;
}
public void swapData(int from, int to) {
//This method is not supported by 'RealmResults' or 'OrderedRealmCollectionSnapshot'.
Collections.swap(usersList, from, to);
}
public void swipeDelete(int position) {
if (null != listener) {
listener.onSwipeToDeleteUser(position);
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public View rootView;
public TextView tvName;
public TextView tvCardNo;
public CheckBox checkbox;
public ViewHolder(View rootView) {
super(rootView);
this.rootView = rootView;
this.tvName = (TextView) rootView.findViewById(R.id.tv_name);
this.tvCardNo = (TextView) rootView.findViewById(R.id.tv_cardNo);
this.checkbox = (CheckBox) rootView.findViewById(R.id.checkbox);
}
}
public interface onItemClickListener {
void onItemClick(Users user);
void onItemLongCick(Users user);
void onSwipeToDeleteUser(int position);
void selectedAll();
}
}
注:realm給recycleview提供了官方的介面卡,很好用,只不過我這次沒有用
3、自定義ItemTouchHelperCallBack
/**
* 自定義ItemTouchHelper.Callback
*/
public class MyItemHelpCallBack extends ItemTouchHelper.Callback {
private UserAdapter adapter;
public MyItemHelpCallBack(UserAdapter adapter) {
this.adapter = adapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允許上下的拖動
int swipeFlags = ItemTouchHelper.LEFT; //只允許從右向左側滑
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//This method is not supported by 'RealmResults' or 'OrderedRealmCollectionSnapshot'.
//realm 不支援 Collections.swap()方法
// adapter.swapData(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.swipeDelete(viewHolder.getAdapterPosition());
}
}