I am implementing a custom recyclerview with switch for item selection. I have a "Select All" option at the right corner of App Bar (top bar). I want to allow user to use Select All option and also allow individual item selection in recyclerview.
I don't know how to implement individual selection along with Select All. When an item is deselected after using the select all option and when the list is scrolled the item gets selected automatically as the isSelectedAll flag is set true in onBindViewHolder method in the below code.
******SELECT ALL CLICK LISTENER IN ACTIVITY CLASS******
mBinding.imageViewActionSelect.setOnClickListener(v -> {
mAdapter.selectAll();
});
******ADAPTER CLASS******
public void selectAll() {
isSelectedAll = true;
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (isSelectedAll) {
holder.mSwitchView.setChecked(true);
}
else
holder.mSwitchView.setChecked(false);
}
First, Add one variable isSelected to your POJO class and then, while you select All option, make that variable true by running your list of items in a loop, and then call adapter.notifyDataSetChanged(). Now when you select or deselect individual items make that isSelected variable true or false according to your needs and dont forget to call notifyDataSetChanged(). You are good to go.
You could use this FastAdapter library: https://github.com/mikepenz/FastAdapter . Single select is easy, its already done for you. For multi select, you could just loop through all your items and call mAdapter.toggleSelection(position) . When you need the selected items you could easily call mAdapter.getSelection() . Its that easy, no need to do stuff yourself
Related
I have an app where on click of an item I am updating the background image in viewholder in adapter. However, i want to do it such that when I click on one item all other items revert to default images( sort of like toggle back ). Say I have a play button on item 1 and I click it, it switches to pause, then I click on item 2 and it switches to pause and the first button in item 1 switches back to play button. Is there a way to do that in recycler view?
Here's my code in onclick:
#Override
public void onClick(View v) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
if(!tracks.get(getAdapterPosition()).getMediaUrl().equals(currenturl) ){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
currenturl = tracks.get(getAdapterPosition()).getMediaUrl();
currentposition = getAdapterPosition();
playAudio(tracks.get(getAdapterPosition()).getMediaUrl());
}
I want to update the currently clicked image such that
mediaUrl.setBackgroundResource(android.R.drawable.ic_media_pause);
for the current item, but reverts back to
mediaUrl.setBackgroundResource(android.R.drawable.ic_media_play);
for the previous item clicked , or can be refreshed to the default value for all other items in the recycleview. Any idea how to go about this in the easiest way posssible? Thanks!
create variable inside your recyclerview adapter itemselected = "number of currently selected item".
in your viewHolder bind check the itemSelectedIndex and apply the style appropriately.
Make onClickListener for the event where you waht to select some item. In the onClick set the itemSelectedIndex = "item number which was clicked". And then call (also in the same method) notifyDataSetChahged.
This will do the job.
notifyDataSetChanged will make your recyclerview to redraw whole item. And, since the "selected" view will also be applied to the itemSelectedIndex item, others will turn unselected.
In order to improve performance of this solution you might want to introduce two indexes:
itemSelected
itemSelectedPrevious.
In this case, in onClick do:
itemSelectedPrevious = itemSelected
itemSelected = "index of current clicked item"
notifyItemChanged(itemSelectedPrevious)
notifyItemChanged(itemSelected)
in this case you'll avoid redrawing of the whole recycleradapter view, but will only update previously selected item to change it's state to non-selected, and also the current item to be active.
Hope this helps :)
I have a tour list in android and I am trying to implementing add to favorites.
Favorite works for the list that is added in myTours but doesn't work for tours from search list.
This is the code:
private List<Tour> tourList;
holder.imgFavourite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(tourList.get(position).getFav().equalsIgnoreCase("0")) {
tourList.get(position).setFav("1");
// listener.onFavourited(tourList.get(position), true);
holder.imgFavourite.setImageResource(R.drawable.faved);
} else {
tourList.get(position).setFav("0");
// listener.onFavourited(tourList.get(position), false);
holder.imgFavourite.setImageResource(R.drawable.not_faved);
}
}
});
Here when I click on Fav icon gets changed to faved. But if I search for different category and again come back to that category state doesn't persist.
Any help would be appreciated.
Listview/RecyclerView reuses views. If your list has 20 items and 4 are visible at one time, as you scroll, the views are reused to show the new visible views to save memory. So if you alter the view at position 5 and scroll down and scroll back up to position 5, the view that you changed in position 5 is not the same view that you are seeing after you scroll back up. Hence the view changes
To fix this, maintain a global variable in the adapter which stores the favorite position and in the onBindViewHolder, add a condition like
if(position = favPosition)
<Change to fav view>
else
<Change to Normal View>
The else condition is really important or else multiple views will have the Fav view
For recycler view always consider both cases only one case cause your list to change behaviour(like set same image for other list item because it reuses the cell for your view).the below mistake you are doing.
In bindviewholder you are getting data from model class and based on that you set resources for imageview.which is good.
But the problem is there no case for failing of the condition so you are losing the state and if you scroll down and again come to this item you lost your state or face behaviour that goes against your requirement.
So simply provide case for not matching your condition.
I'm using android:checkableBehavior="single" within a group, this group contains few items, those items represents content filters, there is no default filter(meaning there is not always has to be a checked item, at least that what I wants), if I click a filter and want to disable it I can click it again and my expectation is that by using setChecked(false) the item will unchecked.
However, it looks like:
For checkableBehavior="single" setChecked() will always check the menu
item even if parameter is 'false' because of Google implementation.
My obvious solution is adding a no filter item that can be checked by the users to indicates they don't want a filter but it's just seems more intuitive to check and uncheck the same item, it there another way to setChecked(false)?
Google's brain-dead implementation in MenuItemImpl (as of Nougat):
#Override
public MenuItem setChecked(boolean checked) {
if ((mFlags & EXCLUSIVE) != 0) {
// Call the method on the Menu since it knows about the others in this
// exclusive checkable group
mMenu.setExclusiveItemChecked(this);
} else {
setCheckedInt(checked);
}
return this;
}
Note that checked is completely ignored when the EXCLUSIVE flag is set.
I've got this RecyclerView, it's showing a list of persons with their names, phones and birthday.
I want to change the color of the item if the person's birthday is today, but I want to know if I should do the verification and change on my RecyclerView's adapter inside the OnBindViewHolder method, or if I should do it inside my activity calling my LinearLayoutManager or calling the item using the RecyclerView.getChildAt() method.
Should I go whit the first option, using the onBindViewHolder?
YES . Should you choose to make changes in the onBindViewHolder().
We'll take a sample:
#Override
public void onBindViewHolder(FeedsViewHolder feedViewHolder, int i)
{
if(d1.feeds.get(i).getFeedContentType().equals("b-day")) // <-- Pointing to the List that contains value, and checks if it equals to a sample string
{
feedViewHolder.n1.setText("Birthday"); // <-- if it equals, party time :D , and sets text to the corresponding TextView in the RecyclerView
}
}
Hope it helps :)
I need to handle the selected row in listview on long click on the row but because am using menus I can't override the onclicklistener. I am trying to do this:
listView.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
taskPosition = listView.getSelectedItemPosition();
return true;
}
});
but it doesn't work. Can anyone help me?
i got the value of listView.getSelectedItemPosition(); is equal -1
Of course. Rows typically are not selected. Rows are only selected if the user is using a pointing device (D-pad, trackball, etc.).
i need to handle the selection longclick on listview and use it in onContextItemSelected to perform action
No, you don't. You either use context menus or you use a long-click listener with a widget. You do not use both.
If you are trying to determine what row was long-clicked from onContextItemSelected(), here is a sample project that will demonstrate that for you, if your adapter is an ArrayAdapter. If you are using a CursorAdapter, here is a different sample project that will demonstrate this for you.