This is really weird.
When I use the standard ArrayAdapter for a ListView calling setItemChecked works OK
But when using a custom made ArrayAdapter it does n
None of the responses worked for me. My problem was that only the initial call to ExpandableListView.setItemChecked from OnCreate/OnStart/OnPause did not work as if the view was not fully initialized yet. In order to solve this, I had to do the following:
_expandableListView.Post(() =>
{
_expandableListView.SetItemChecked(fragmentPosition, true);
});
Checkable is a learning curve I prefer not to take right now. You can set and unset the CheckBox manually in the Activities' OnItemClickListener
. Maintain a boolean isChecked
transient variable in the MyObject
list in the ArrayAdapter<MyObject>
.
public void onItemClick(AdapterView<?> av, View v, int position, long arg3) {
final ListView listView = (ListView) findViewById(android.R.id.list);
MyObject item = (MyObject) listView.getItemAtPosition(position);
item.isChecked = !item.isChecked;
if(item.isChecked)
addItem(item);
else
removeItem(item);
}
To account for users clicking the CheckBox
itself; use the same addItem(item)/removeItem(item) logic in your custom array adapter's getView
implementation, in the CheckBox
's OnClickListener
.
public View getView(int position, View convertView, ViewGroup viewGroup) {
CheckBox cb = null;
if (convertView == null) {
if(inflater == null) //cache to avoid reconstructing for each view
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView =inflater.inflate(R.layout.list_item_text_right_checkmark, null);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.check);
cb.setChecked((list.get(position).isChecked));
cb.setTag(list.get(position);
public void onClick(View v) {
if(v instanceof CheckBox) {
CheckBox cb = (CheckBox) v;
if(cb.isChecked()) //verify boolean logic here!!!
activityRef.get().addItem(cb.getTag()); //WeakReference to activity
else
activityRef.get().removeItem(cb.getTag());
}
});
} else cb = (CheckBox) convertView.findViewById(R.id.check);
cb.setChecked((list.get(position).isChecked));
...
}
Calling CheckBox::setChecked() is the key here.
This seems to do the trick as long as your array adapter can assume the same activity, and your array adapter can assume the same list item xml definition in res/layout/.
checkable list item XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/check"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:focusable="false"/>
</RelativeLayout>
If you need to check some of your CheckBoxs initially, just set your isChecked members in your MyObject prior to inflating.
For sure you have to set the choice mode for your ListView, for example:
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
But if you're also using a custom layout for your list item (R.layout.drawing_list_item
), then you have to make sure your layout implements the Checkable interface:
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private boolean isChecked = false;
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
changeColor(isChecked);
}
public void toggle() {
this.isChecked = !this.isChecked;
changeColor(this.isChecked);
}
private void changeColor(boolean isChecked){
if (isChecked) {
setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
} else {
setBackgroundColor(getResources().getColor(android.R.color.transparent));
}
}
}
Then your checkable layout will be defined as the following example:
<?xml version="1.0" encoding="utf-8"?>
<it.moondroid.banking.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<ImageView
android:id="@+id/agenzie_item_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@android:color/darker_gray"
android:focusable="false" />
<TextView
android:id="@+id/agenzie_item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/agenzie_item_icon"
android:focusable="false"
android:paddingLeft="10dp"
android:text="item"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF" />
</it.moondroid.banking.CheckableRelativeLayout>
Your row layout needs to be Checkable
for setItemChecked()
to work, in which case Android will manage calling setChecked()
on your Checkable
as the user clicks on the row. You would not need to be setting up your own OnCheckedChangeListener
.
For more, see: