ListView with CheckBox
Today I am going to show how to deal with Custom ListView having Chekbox. Many developers are facing the issue of Checkbox item getting uncheck or check while scrolling the ListView. So, I will make it clear to developers how to deal with ListView having Checkbox.
The issue with CheckBox inside ListView is that the view gets recycled due to recycling of ListView and the value of Checkbox(check or uncheck) is not maintained. To, maintain the state to CheckBox there has to be something that can store the state of Checkbox.
So, we have a Model class that will have name and selected property of ListView row having TextView and CheckBox.
Model.java
public class Model {
private String name;
private boolean selected;
public Model(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
The issue with CheckBox inside ListView is that the view gets recycled due to recycling of ListView and the value of Checkbox(check or uncheck) is not maintained. To, maintain the state to CheckBox there has to be something that can store the state of Checkbox.
So, we have a Model class that will have name and selected property of ListView row having TextView and CheckBox.
Model.java
public class Model {
private String name;
private boolean selected;
public Model(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
Now, we will setup the main Activity that will set the Adapter for the Custom ListView.
MainActivity.java
public class MainActivity extends Activity implements OnItemClickListener{
ListView listView;
ArrayAdapter<Model> adapter;
List<Model> list = new ArrayList<Model>();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
listView = (ListView) findViewById(R.id.my_list);
adapter = new MyAdapter(this,getModel());
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
TextView label = (TextView) v.getTag(R.id.label);
CheckBox checkbox = (CheckBox) v.getTag(R.id.check);
Toast.makeText(v.getContext(), label.getText().toString()+" "+isCheckedOrNot(checkbox), Toast.LENGTH_LONG).show();
}
private String isCheckedOrNot(CheckBox checkbox) {
if(checkbox.isChecked())
return "is checked";
else
return "is not checked";
}
private List<Model> getModel() {
list.add(new Model("Linux"));
list.add(new Model("Windows7"));
list.add(new Model("Suse"));
list.add(new Model("Eclipse"));
list.add(new Model("Ubuntu"));
list.add(new Model("Solaris"));
list.add(new Model("Android"));
list.add(new Model("iPhone"));
list.add(new Model("Java"));
list.add(new Model(".Net"));
list.add(new Model("PHP"));
return list;
}
}
ListView listView;
ArrayAdapter<Model> adapter;
List<Model> list = new ArrayList<Model>();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
listView = (ListView) findViewById(R.id.my_list);
adapter = new MyAdapter(this,getModel());
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
TextView label = (TextView) v.getTag(R.id.label);
CheckBox checkbox = (CheckBox) v.getTag(R.id.check);
Toast.makeText(v.getContext(), label.getText().toString()+" "+isCheckedOrNot(checkbox), Toast.LENGTH_LONG).show();
}
private String isCheckedOrNot(CheckBox checkbox) {
if(checkbox.isChecked())
return "is checked";
else
return "is not checked";
}
private List<Model> getModel() {
list.add(new Model("Linux"));
list.add(new Model("Windows7"));
list.add(new Model("Suse"));
list.add(new Model("Eclipse"));
list.add(new Model("Ubuntu"));
list.add(new Model("Solaris"));
list.add(new Model("Android"));
list.add(new Model("iPhone"));
list.add(new Model("Java"));
list.add(new Model(".Net"));
list.add(new Model("PHP"));
return list;
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/my_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/my_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
row.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="wrap_content" >
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="30sp" >
</TextView>
<CheckBox
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="4dip"
android:layout_marginRight="10dip"
android:focusable="false"
android:focusableInTouchMode="false" >
</CheckBox>
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@+id/label"
android:textSize="30sp" >
</TextView>
<CheckBox
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginLeft="4dip"
android:layout_marginRight="10dip"
android:focusable="false"
android:focusableInTouchMode="false" >
</CheckBox>
</RelativeLayout>
Finally, now we will have the Adapter class.
MyAdapter.java
public class MyAdapter extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
boolean checkAll_flag = false;
boolean checkItem_flag = false;
public MyAdapter(Activity context, List<Model> list) {
super(context, R.layout.row, 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) {
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.check);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
}
});
convertView.setTag(viewHolder);
convertView.setTag(R.id.label, viewHolder.text);
convertView.setTag(R.id.check, viewHolder.checkbox);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkbox.setTag(position); // This line is important.
viewHolder.text.setText(list.get(position).getName());
viewHolder.checkbox.setChecked(list.get(position).isSelected());
return convertView;
}
}
private final List<Model> list;
private final Activity context;
boolean checkAll_flag = false;
boolean checkItem_flag = false;
public MyAdapter(Activity context, List<Model> list) {
super(context, R.layout.row, 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) {
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.check);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
}
});
convertView.setTag(viewHolder);
convertView.setTag(R.id.label, viewHolder.text);
convertView.setTag(R.id.check, viewHolder.checkbox);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkbox.setTag(position); // This line is important.
viewHolder.text.setText(list.get(position).getName());
viewHolder.checkbox.setChecked(list.get(position).isSelected());
return convertView;
}
}
So, the important line in the above Adapter class is to setTag() position of CheckBox and then retrieve it using getTag() inside onCheckedChanged() and then set the current state of CheckBox in your Model class instance. I am also attaching the complete source code for the same so that anyone can download and understand that how it works
Comments
Post a Comment