
مدتی بود برای پروژه ای دنبال روشی میگشتم تا بتونم multi selection رو برای recyclerView پیاده کنم اما آموزش هایی که توی وب پیدا کردم یا پیچیده پیادهسازی شده بودن یا به زبان کاتلین نوشته شده بودن که خوندنش برام به راحتی جاوا نبود.
در نهایت بعد از چند روز سر و کله زدن با نمونه کد های مختلف موفق شدم به نتیجه ای که میخوام برسم و به نظرم اومد پستی دربارش بنویسم. امیدوارم که مفید واقع بشه.
برای این آموزش ما قراره از کتابخونه ای که خود اندروید ارائه داده استفاده کنیم که داکیومنت های مربوط بهش رو میتونید اینجا ببینید.
توصیه میکنم از AndroidX استفاده کنید برای اینکار از این مسیر اقدام کنید : Refactor > Migrate to AndroidX
دو خط زیر رو به (build.gradle (Module App پروژتون اضافه کنید و sync رو بزنید.
implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.recyclerview:recyclerview-selection:1.0.0'
خب بعد از اینکه آماده سازی های بالا رو انجام دادین اولین قدم ساختن یک recyclerView هست. با فرض اینکه پیاده سازی اون رو بلد هستین (اگر نه اینجا رو کلیک کنید) من فقط خلاصه ای از مراحل رو مینویسم.

تا اینجا اگر از اپ اجرا بگیرین باید یه recyclerView ساده مشابه عکس بالا داشته باشین.
اولین قدم تعیین نوع selection key هست که مشخص کردن آیتم های انتخاب شده رو بر عهده داره; میتونید از سه نوع parcelable , long , string استفاده کنید که من اینجا از long استفاده کردم.
متد getViewHolderItemDetails
public ItemDetailsLookup.ItemDetails<Long> getViewHolderItemDetails() { return new ItemDetailsLookup.ItemDetails<Long>() { @Override public int getPosition() { return getAdapterPosition(); } @Nullable @Override public Long getSelectionKey() { return getItemId(); } }; }
این متد رو باید در ادامه کلاس ViewHolder که قبلا پیاده سازی کردین اضافه کنید. مقداری از جنس <ItemDetails<Long رو برمیگردونه که در واقع حاوی اطلاعاتی درباره ViewHolder ای هست که کاربر اون رو انتخاب کرده (شامل selection key و position هست). در ادامه قراره از اون استفاده کنیم.
کلاس MyItemDetailsLookup
public class MyItemDetailsLookup extends ItemDetailsLookup<Long> { private RecyclerView recyclerView; public MyItemDetailsLookup(RecyclerView recyclerView) { this.recyclerView = recyclerView; } @Nullable @Override public ItemDetails<Long> getItemDetails(@NonNull MotionEvent e) { View view = recyclerView.findChildViewUnder(e.getX() , e.getY()); if (view != null) { return ((ViewHolder)recyclerView.getChildViewHolder(view)) .getViewHolderItemDetails(); } return null; } }
وظیفه این کلاس فراهم کردن اطلاعات درباره آیتم انتخاب شده برای استفاده کتابخانه selection هست.
کلاس ModelAdapter
این کلاس رو قبلا برای RecyclerView نوشته بودیم اما برای پیاده کردن selection باید چند متد رو بهش اضافه کنیم.
setHasStableIds(true);
@Override public long getItemId(int position) { return (long)position; }
SelectionTracker<Long> tracker; public void setTracker(SelectionTracker<Long> tracker) { this.tracker = tracker; }
if (tracker != null) { //if item is selected , change the color of views if (tracker.isSelected((long)position)) { holder.nameTV.setTextColor(Color.RED); holder.phoneTV.setTextColor(Color.RED); holder.container.setBackgroundColor(Color.LTGRAY); } //if item is not selected or deselected change color to default else { holder.nameTV.setTextColor(Color.BLACK); holder.phoneTV.setTextColor(Color.BLACK); holder.container.setBackgroundColor(Color.WHITE); } }
در نهایت مقدار دهی به tracker
tracker = new SelectionTracker.Builder<>("selection1" , recyclerView , new StableIdKeyProvider(recyclerView) , new MyItemDetailsLookup(recyclerView) , StorageStrategy.createLongStorage()) .withSelectionPredicate(SelectionPredicates.<Long>createSelectAnything()) .build(); //set tracker to adapter modelAdapter.setTracker(tracker);