在查看RecyclerView的官方文檔的時候發現了這個recyclerview-selection庫,通過測試感受功能挺好的,省去了本身須要編寫大量多選功能的代碼,官方文檔的guide又不是太清晰,這篇文章僅僅做爲簡單的記錄。html
參考:java
根據官方文檔的描述,這個庫就是用來處理RecyclerView的Item的選擇問題,而且能夠在設備配置改變的時候保存已選擇的數據,從新建立頁面的時候再次加載,省去了咱們本身對這部分的操做;同時經過觀察者模式提供了item點擊監聽、長按訂閱功能。 android
public class StringItemKeyProvider extends ItemKeyProvider<String> {
private List<String> items;
public StringItemKeyProvider(int scope, List<String> items) {
super(scope);
this.items = items;
}
@Nullable
@Override
public String getKey(int position) {
return items.get(position);
}
@Override
public int getPosition(@NonNull String key) {
return items.indexOf(key);
}
}
複製代碼
ItemDetails getItemDetails(@NonNull MotionEvent e)
方法,經過ReyclerView的findChildView(int,int)
方法來判斷具體touch的是哪個Item,強轉成咱們的ViewHolder類型,調用咱們RecyclerView.ViewHolder中的方法來返回一個ItemDetails實例,返回實例的方法是咱們本身添加的,ViewHolder中並無該抽象方法;public class StringItemDetailsLookup extends ItemDetailsLookup {
private final RecyclerView mRecyclerView;
StringItemDetailsLookup(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
}
@Nullable
@Override
public ItemDetails getItemDetails(@NonNull MotionEvent e) {
View view = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
if (view != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(view);
if (holder instanceof StringItemRecyclerViewAdapter.ItemViewHolder) {
return ((StringItemRecyclerViewAdapter.ItemViewHolder) holder).getItemDetails();
}
}
return null;
}
}
複製代碼
如下是返回ItemDetails實例的方法,其中註釋的語句是經過繼承ItemDetails的子類來建立的。git
ItemDetailsLookup.ItemDetails getItemDetails() {
// return new StringItemDetail(getAdapterPosition(),datas.get(getAdapterPosition()));
return new ItemDetailsLookup.ItemDetails() {
@Override
public int getPosition() {
return getAdapterPosition();
}
@Nullable
@Override
public Object getSelectionKey() {
return datas.get(getAdapterPosition());
}
};
}
複製代碼
public class StringItemDetails extends ItemDetailsLookup.ItemDetails {
private int position;
private String item;
public StringItemDetails(int position, String item) {
this.position = position;
this.item = item;
}
@Override
public int getPosition() {
return position;
}
@Nullable
@Override
public Object getSelectionKey() {
return item;
}
}
複製代碼
如今咱們準備好了StringItemDetailsLookup
、StringItemKeyProvider
兩個類,可是準備好了又怎麼用呢?github
android:persistableMode
屬性纔會調用,一樣onSaveInstanceState
、onRestoreInstanceState
也是如此,mAdapter = new StringItemRecyclerViewAdapter(ITEMS);
mRecyclerView.setAdapter(mAdapter);
mSelectionTracker = new SelectionTracker.Builder<>(
"string-items-selection",
mRecyclerView,
new StringItemKeyProvider(1, ITEMS),
new StringItemDetailsLookup(mRecyclerView),
StorageStrategy.createStringStorage())
//設置可選擇的item,這裏設置爲均可選
.withSelectionPredicate(SelectionPredicates.<String>createSelectAnything())
.build();
mAdapter.setSelectionTracker(mSelectionTracker);
複製代碼
注意上邊setSelectionTracker
方法,這個方法是咱們在自定義的RecyclerView.Adapter中添加的,目的是將咱們建立的SelectionTracker注入到咱們的Adpter。bash
public void setSelectionTracker(SelectionTracker mSelectionTracker) {
this.mSelectionTracker = mSelectionTracker;
}
複製代碼
前邊說了,咱們在Adapter中添加了getItemDetails
方法,如今咱們的基本工做已經完成,程序能正常運行了,可是咱們還看不到多選的效果,由於tracker並不能爲咱們提供選中高亮功能,高亮功能按咱們喜歡的方式實現便可,判斷是否選中的代碼以下(在Adapter的onBindViewHolder方法中):ide
if (mTracker.isSelected(datas.get(i))) {
viewHolder.tvInfo.setBackgroundColor(Color.parseColor("#80deea"));
} else {
viewHolder.tvInfo.setBackgroundColor(Color.WHITE);
}
複製代碼
onSaveInstanceState
、onRestoreInstanceState
中分別調用tracker的onSaveInstanceState
、onRestoreInstanceState
方法便可,以下:@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
mSelectionTracker.onRestoreInstanceState(savedInstanceState);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mSelectionTracker.onSaveInstanceState(outState);
}
複製代碼
咱們能夠爲tracker添加訂閱事件或者item單擊事件,這樣選擇狀態改變或者item被點擊是咱們能夠添加本身的邏輯,後續多選操做及多選信息咱們均可以經過tracker的事件或者方法得到,具體請看參考3的代碼或者查看官網SelectionTracker的說明。測試
最後,必須第一步的操做,Android studio 3.4居然沒法直接搜索recyclerview添加其依賴,搜索結果是androidx版本的,會有衝突,recyclerview-selection卻是能夠直接搜索依賴到項目中。ui
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:recyclerview-selection:28.0.0'
複製代碼