When i click on the first item of ListView, the first item is selected. But when i scroll down, the 12th item is selected too, but i didn;t click on the 12th item. Why it was happend?
First screen: http://oi59.tinypic.com/9iw7b8.jpg
Second screen : oi60.tinypic.com/1zxunv4. jpg [delete whitespace]
My sourse code is like that :
http://startandroid.ru/en/uroki/vse-uroki-spiskom/85-urok-44-sobytija-v-listview.html
But i add the white recolor after utem click.
This question was answered here: Checking a checkbox in listview makes other random checkboxes checked too
Basically, when you scroll down you list, it recycles its present state as well as listeners attached to it.
One way I solved this problem is (suposing that your list is called check in java):
Create a boolean array (let's name it listCheck), same size as your checkbox, all values false
Write in your adapter getView method:
check.setChecked(listCheck[position]); //listCheck is your array of booleans.
check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox checkBox = (CheckBox) v.findViewById(R.id.checkEspecialidade);
listCheck[position] = check.isChecked();
}
});
Basically, we set the check value the same as the one on the array, and when the user clicks it, we also change de value of that check in the array. That works because the boolean array is not recycled.
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 have a list with items that have checkBox, and I need that only one checkBox to be selected at a time. I cannot use listView with singleChoice nor RadioButtons. Below is my code I am using but I do not know why is not working.
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (selectedCheckBox != null) {
// simulate radio group behavior
selectedCheckBox.setChecked(false);
selectedCheckBox = null;
}
if (isChecked) {
selectedCheckBox = (CheckBox) buttonView;
}
}
The problem is that the checkBoxes still remain checked and I do not know why regarding that I set the previous selectedCheckBox to false. Could anyone explain what happens? Thanks
UPDATE
I tested on a Nexus 5 with Android 5.0 and it works on that. On Android versions < 5.0 seems to have the problem I mentioned.
You need to call: notifyDataSetChanged() of your ListView Adapter. If not your data in your ListView is not going to refresh and your checkboxes will remain selected.
If you have one checkbox in each ListView item, you must loop the entire "other" (that must be unchecked) items, and uncheck it. It's not a practical approach.
I usually use a Arraylist to fill Listview. In array list there must be objects like boolean fields. So when a checkbox is checked or unchecked it means that the boolean field is changed to false or true, and then the list view is reproduced. If you follow this way, then it must be easy, first loop through Arraylist and change all booleans to false, then change the selected one to true, that is all, then android will refresh view for you. Hope it help.
I have an issue with the Spinner in Android. Selecting an item from the dropdown will adjust the offset of that dropdown the next time it is opened. So for example if I choose item 100 in a 500 item dropdown, the next time I open the dropdown, item 100 will be at the top of the list. This is the behaviour I want.
There seems to be an issue when I combine the selector functionality with calling setSelection(int). With the following steps I seem to have broken the offset system on dropdown spinners.
Open the Spinner and select the second item.
Open the Spinner again and this time dismiss it without selecting anything.
Call setSelection(int) on the Spinner with a value greater than 2.
Open the Spinner a third time. Note that the offset is the same as back in Step 1.
I've taken a look at the code in Spinner and AdapterView, but I can't see anything public calls that I've missed. Is this a bug in Spinner or a bug in my code?
Did you try public void setSelection (int position, boolean animate)? I haven't tried it, but I think passing true as the second parameter should make the list scroll to the selected position. The other alternative is to calculate the scroll offset (item height x selected item position) and call setDropDownVerticalOffset.
Update: I tried modifying the Spinner example in API demos to use setSelection(7, true) and it seems to work when following the 4 steps you provided in your question. I just added a Handler and modified showToast as follows:
private final Handler handler = new Handler();
void showToast(CharSequence msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
handler.postDelayed(new Runnable(){
public void run() {
Toast.makeText(Spinner1.this, "auto setting", Toast.LENGTH_SHORT).show();
Spinner s2 = (Spinner) findViewById(R.id.spinner2);
s2.setSelection(7, true);
}
}, 5000);
}
I tested as follows:
open the second spinner and picking 'Venus' (the second selection).
open the second spinner, then press back to dismiss
after 5 seconds, the postDelayed call causes 'Neptune' (the seventh selection) to be selected
open the spinner and the offset is correct
I think you can solve that problem with sending List to Adapter. When an item selected, sort your List then use notifyDataSetChanged() function of adapter. When you called setSelection(int) function again sort your List and use notifyDataSetChanged() function.
I'm now developing an application that uses a ListView with a
CheckedTextView on every item that managed by an ArrayAdapter to
support multiple chooses. The contents in my ListView are dynamic, that
means, can be changed during runtime. Now I try to use
ListView.getCheckedItemPositions() to get all checked items, Because I want
to save all the checked positions and auto-check them when user go back to
this page again. So I need to save checked results for every page.
For the first page everything works fine as expected. But when user goes to
another page and make some chooses, the result array that ListView returned
contains some positions that are never checked. I don't why ListView has
this strange behavior. Even for a page that in fact no checked happens but
ListView gives me a result that indicates there's one item has been checked.
could anyone who can teach me how to get the position of CheckedTextView
in its OnClickListener callback?
example code is appreciate.
Thanks in advance...
The listview recycles its views so when you go to a different page and then return to the previous page, the listview recalls the getView() function for its views. To make sure that the order of the checked views are not mixed up, create an arraylist that contains the check state of all the views before initializing the adapter. Then pass the arraylist as an argument for the adapter's constructor. There, in the getView() function, set the checked state of each checkable textview based on the arraylist. Then, return to the activity class and override the onItemClick() event. Using the view that is given to you when the function is called, do the following to get the checkable textview and set its checked state:
listView1.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View selectedView, int position , long id)
{
CheckedTextView tv = (CheckedTextView)selectedView.findViewById(R.id.textview);
if (tv.isChecked())
{
tv.setChecked(false);
checkStatesOfViews.get(position) = false;
}
else
{
tv.setChecked(true);
checkStatesOfViews.get(position) = true;
}
}
});