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 not.
What would be the reason? Is this a bug? Or am I missing something?
public class Test_Activity extends Activity {
/** Called when the activity is first created. */
private List<Model> list;
private ListView lView;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
setContentView(R.layout.main);
lView = (ListView) findViewById(R.id.ListView01);
lView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list = getModel();
//with this adapter setItemChecked works OK
lView.setAdapter(new ArrayAdapter<Model>(this,
android.R.layout.simple_list_item_multiple_choice, list));
//**************************
//PROBLEM: with this adapter it does not check any items on the screen
// ArrayAdapter<Model> adapter = new Test_Class1(this, list);
// lView.setAdapter(adapter);
}
private List<Model> getModel() {
List<Model> list = new ArrayList<Model>();
list.add(get("0"));
list.add(get("1"));
list.add(get("2"));
list.get(1).setSelected(true);
Model m = list.get(1);
list.add(get("3"));
list.add(get("4"));
list.add(get("5"));
list.add(get("6"));
list.add(get("7"));
// Initially select one of the items
return list;
}
private Model get(String s) {
return new Model(s);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.results_screen_option_menu, menu);
return true;
}
/**
* @category OptionsMenu
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_all: {
int size = lView.getAdapter().getCount();
for (int i = 0; i <= size; i++) {
//************************** PROBLEM
lView.setItemChecked(i, true); // selects the item only for standard ArrayAdapter
Log.i("xxx", "looping " + i);
}
}
return true;
case R.id.select_none:
return true;
}
return false;
}
}
//------------------------------------------------------------
public class Test_Class1 extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
public Test_Class1(Activity context, List<Model> list) {
super(context, R.layout.rowbuttonlayout2, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
Log.i("xxx", "-> getView " + position);
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
Log.i("xxx", "-> onCheckedChanged");
element.setSelected(buttonView.isChecked());
Log.i("xxx", "<- onCheckedChanged");
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
Log.i("xxx", "holder.checkbox.setChecked: " + position);
holder.checkbox.setChecked(list.get(position).isSelected());
Log.i("xxx", "<- getView " + position);
return view;
}
}
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:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With