I have followed the tutorial here to create a custom ListView
that shows items with category headers. I have modified the list_item_entry.xml
to put a CheckBox
in the item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingRight="?android:attr/scrollbarSize" >
<CheckBox
android:id="@+id/option_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
android:focusable="false"
android:clickable="false" />
<TextView
android:id="@+id/list_item_entry_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
</LinearLayout>
My problem is that if I check some of the CheckBoxes
then scroll them off the screen, when they come back they are unchecked. However listView.getCheckedItemPositions()
still shows that the item is checked
.
I'm pretty sure that my problem is with the getView()
method in my custom ArrayAdapter
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item i = items.get(position);
if (i != null) {
if(i.isSection()){
SectionItem si = (SectionItem)i;
convertView = vi.inflate(R.layout.list_item_section, parent, false);
convertView.setOnClickListener(null);
convertView.setOnLongClickListener(null);
convertView.setLongClickable(false);
final TextView sectionView =
(TextView) convertView.findViewById(R.id.list_item_section_text);
sectionView.setText(si.getTitle());
}else{
EntryItem ei = (EntryItem)i;
convertView = vi.inflate(R.layout. list_item_entry, parent, false);
final TextView title =
(TextView) convertView.findViewById(R.id.list_item_entry_title);
if (title != null)
title.setText(ei.getTitle());
}
}
return convertView;
}
I think that I have two issues here, though I have no idea how to solve either:
Using vi.inflate
every time is causing android to constantly create views which is bad (not sure about this). I tried to only inflate it if convertView == null
but then sometimes convertView
would be in the wrong format, ie. List_item_section
when it should be List_item_entry
. Is it fine to inflate it everytime?
I think that inflating the view each time is causing the CheckBoxes
to be reset, although I may be wrong about this.
So how do I make it so the CheckBoxes will stay checked when the leave and return to the screen? And will this method fill Android's memory with Views if the the list is sufficiently long?
Update:
I liked @user3815165's answer because I didn't need to store the checked
value for a sectionItem
which doesn't have a checkbox. But as I mentioned in a comment, since the items
list is not in the context of the Activity then the values of whether each EntryItem
is checked or not persists when the view is destroyed and creates bugs.
So I decided to go with @Palash's answer, even though it stored data not needed (only a single boolean
value for each SectionItem
in the list). It works perfectly.
you need to maintain a status array of type boolean in your activity, pass that array into your list adapter and while setting the checkbox check status of that position, also you need to update that status array likewise on click event of checkbox. try this you will get the desired output.
//While Setting the checkbox in adapter
if(bStatus[position]==false)
{
itemSet.chSelectItem.setChecked(false);
}else if(bStatus[position]==true)
{
itemSet.chSelectItem.setChecked(true);
}
In your main Activity
//initilize Arraylist in main Activity
boolean[] bStatus;
bStatus = new boolean[BeanArray.size()];
Arrays.fill(bStatus, false);
MyAdapter adapter = new MyAdapter(this, BeanArray, bStatus);
listView.setAdapter(adapter);