I have columns of checkboxes, the top row of which are CheckAll checkboxes for that particular column. If I uncheck the Checkall from the first CheckAll checkbox in the leftmost column I would like to uncheck the remaining CheckAll checkboxes.
However the mycheckbox.setSelected(false) has no effect. If however, I do a mycheckbox.setEnabled(false) (just as a test) it DOES work and the checkbox is disabled.
By the way, this is a "header row" for a listview with a custom adapter. The contents of the listview work as expected.
Any idea how to get the checkbox unchecked?
You should use mycheckbox.setChecked(false) instead of setSelected.
I've tried searching for setSelected to see what it does, but in official documentation of the CheckBox, I was not able to find it (which suggested to me that this method is probably found in one of the parent classes of CheckBox). Tried typing it in Android Studio:
CheckBox cb = new CheckBox(getApplication());
cb.setSelected(true);
Went to the implementation of the method (CTRL+Click) and saw this in the TextView class, from which almost every other widget is derived:
#Override
public void setSelected(boolean selected) {
boolean wasSelected = isSelected();
super.setSelected(selected);
if (selected != wasSelected && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
if (selected) {
startMarquee();
} else {
stopMarquee();
}
}
}
Interesting thing to note here is that setChecked method is contained in the CompoundButton class, while setSelected is is TextView. That means that setSelected does something completely different because textView surely cannot be checked/unchecked.
I hope this explains it well.
Related
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 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 a listview, each item has 2 checkboxes, I want one of these to be checked automatically if the other is checked (that is in the same item). But the result I have is that when I check the second checkbox in any item, it is the first checkbox of the first item that is checked! (and not in the same item)
The code of checkboxes in xml:
`
<CheckBox
android:id="#+id/checkBox4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox"
android:onClick="handler"
/>`
The code of the function handler:
`
public void handler(View v) {
CheckBox rb = (CheckBox) findViewById(R.id.checkBox3);
rb.setChecked(true);
}
`
Does anyone know how to solve it and indicate that the checkbox to check is the one in the same item (it has the same id no?) ?
The first problem is that you really don't need the handler() method at all. A CheckBox's default behavior is to check when it is clicked, without you calling setChecked(). setChecked() is typically used when you want to explicitly check or uncheck a CheckBox outside of the standard click-to-check/uncheck flow.
However, if you really want the handler method to work (and assuming all of your CheckBoxes call hanlder() on click), you may find you have better luck using the View that is passed to the function as so:
public void handler(View v) {
CheckBox rb = (CheckBox) v;
rb.setChecked(true);
}
Android version: 3.1 API version: Android 2.2 Device: Motorola MX604
I dynamically create a multi-select ListView of CheckedTextView items, and attach a OnItemClickListener to the ListView. In the onItemClick method of the listener, I invoke the isChecked method of CheckedTextView to determine if the associated checkbox is checked or unchecked. Simple enough.
The problem: When I select a previously unselected item, the isChecked method returns false. When I select a previously selected item, the method returns true. The checkbox icon itself checks and unchecks correctly.
Here is the layout for the CheckedTextView:
<CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:drawableLeft="?android:attr/listChoiceIndicatorMultiple"
android:paddingLeft="6dip" android:paddingRight="6dip"
/>
This is how I create the ListView:
private void createSortedChannelList() {
emptyViewContainer();
ListView sortedListView = new ListView(this);
sortedListView.setId(CHANNEL_LISTVIEW_ID);
sortedListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
sortedListView.setItemsCanFocus(false);
sortedListView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
CheckedTextView selectedItem = (CheckedTextView) view;
boolean isChecked = selectedItem.isChecked();
Log.e(mLogTag,"item clicked position = " + position + " isChecked = " + isChecked);
}
});
ArrayAdapter<Channel> listAdapter =
new ArrayAdapter<Channel>(this,R.layout.favorite_channel_list_select_channel_row,mAllChannels);
sortedListView.setAdapter(listAdapter);
for(int channelIndex = 0;channelIndex < mChannelIds.length;channelIndex++){
if(mSelectedChannelIds.contains(mChannelIds[channelIndex]))
sortedListView.setItemChecked(channelIndex, true);
}
addViewToViewContainer(sortedListView);
}
This is the log output that is produced when I select a previously unselected item:
09-23 09:08:59.650: item clicked position = 19 isChecked = false
and when I select a previously selected item
09-23 09:10:20.800: item clicked position = 18 isChecked = true
I have done an extensive search and I can only find one other report of similar behavior. This leads me to believe that the problem probably lies in my code, rather than the android class :p I have also looked at numerous examples that are set up in a similar fashion. Can anyone spot a problem?
thanks
PS This is my first post on any forum, so if I'm missing something that would be helpful to the readers of this post, please let me know.
I believe the code is behaving the way it should. Selecting a previously unselected method will invoke the click listener before changing the checked state of the item in the list. In other words, isChecked() won't return true for the previously unselected item until after the onClick() method is finished.
I've noticed that for me, at least, the behavior of when the state changes isn't consistent; on an emulator, isChecked() returned the pre-click state, but on a device it returned the post-click state.
I got around this by bypassing the "isChecked" altogether, and just looking at the state of the underlying object I am toggling, since that won't change unless I explicitly do so. However, this solution may depend on how your code is set up, and there may be other gotcha's that I am overlooking.
You should be using MultiChoiceModeListener for listening to checks. Here is the documentation
I have an unusual issue with my ListView. I currently have a "deselectAll()" method which iterates through the items in my ListView and sets them to unchecked (the items implement the Checkable interface). The "checked" variable gets changed correctly (the view reports as not being checked), but the visual indicator (in this case, a background change) does not show the view as unchecked (the background stays the color of a checked item).
I am iterating and deselecting through my listview like so (I also added my declerations):
private ListView vw_entryList;
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
((Entry)vw_entryList.getItemAtPosition(i)).setChecked(false);
}
}
The code for my implemented setChecked() is as follows:
public void setChecked(boolean checked) {
_checked = checked;
if (checked) {
setBackgroundResource(R.drawable.listview_checked);
}
else {
setBackgroundResource(R.drawable.listview_unchecked);
}
invalidate();
}
It should be noted that when the items are clicked, they are toggled between checked and unchecked in the OnItemClickListener, and this works ok, with the background change and everything. The code for toggling is very similar:
public void toggle() {
_checked = !_checked;
setBackgroundResource(_checked ?
R.drawable.listview_checked : R.drawable.listview_unchecked);
invalidate();
}
The only difference I can see is where the methods are called from. toggle() is called from within the OnItemClickListener.onClick() method, while my deselectAll() is called from within a button's standard OnClickListener, both in the same class. Does anyone have any ideas as to why the background doesn't change when I call my deselectAll() function?
Do you have custom, non-standard color for the background? If so you might take a look at http://www.curious-creature.org/2008/12/22/why-is-my-list-black-an-android-optimization/ - it boils down to setting android:cacheColorHint attribute of your list to the background color. Maybe that will help.
Edited after further discussion:
I think you need to call getAdapter().notifyDataSetChanged() on the List rather than invalidate(). List is really build in the way that it is relying on adapter to provide the data. What you are doing in fact you have an implicit adapter - Entry is really kept in the adapter and by setting checked, you are changing the data model really, but if you do not call notifyDataSetChanged() the list does not really know that the model has changed and will not recreate the views (invalidate() will only redraw the existing ones).
After trying everything (thanks for your help Jarek), I found a solution that works for my purposes. Instead of implicitly calling the setChecked() within the view that was clicked, I leave it up to the setItemChecked() method within the ListView class.
My updated code:
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
vw_entryList.setItemChecked(i, false);
}
}
My best guess is that the ListView knows that its items implement the Checkable class, and thus requires itself to be the handler of all item operations. Something along those lines. If anyone can explain in more detail why this solution works while the others did not, I'll reward them with the answer and an upvote.