0

I am trying to use the library "android-section-list" with this example code:

public class SectionListActivity extends Activity {

private class StandardArrayAdapter extends ArrayAdapter<SectionListItem> {

    private final SectionListItem[] items;

    public StandardArrayAdapter(final Context context,
            final int textViewResourceId, final SectionListItem[] items) {
        super(context, textViewResourceId, items);
        this.items = items;
    }

    @Override
    public View getView(final int position, final View convertView,
            final ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            final LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = vi.inflate(R.layout.example_list_view, null);
        }
        final SectionListItem currentItem = items[position];
        if (currentItem != null) {
            final TextView textView = (TextView) view
                    .findViewById(R.id.example_text_view);
            if (textView != null) {
                textView.setText(currentItem.item.toString());
            }
        }
        return view;
    }
}

SectionListItem[] exampleArray = { // Comment to prevent re-format
new SectionListItem("Test 1 - A", "A"), //
        new SectionListItem("Test 2 - A", "A"), //
        new SectionListItem("Test 3 - A", "A"), //
        new SectionListItem("Test 4 - A", "A"), //
        new SectionListItem("Test 5 - A", "A"), //
        new SectionListItem("Test 6 - B", "B"), //
        new SectionListItem("Test 7 - B", "B"), //
        new SectionListItem("Test 8 - B", "B"), //
        new SectionListItem("Test 9 - Long", "Long section"), //
        new SectionListItem("Test 10 - Long", "Long section"), //
        new SectionListItem("Test 11 - Long", "Long section"), //
        new SectionListItem("Test 12 - Long", "Long section"), //
        new SectionListItem("Test 13 - Long", "Long section"), //
        new SectionListItem("Test 14 - A again", "A"), //
        new SectionListItem("Test 15 - A again", "A"), //
        new SectionListItem("Test 16 - A again", "A"), //
        new SectionListItem("Test 17 - B again", "B"), //
        new SectionListItem("Test 18 - B again", "B"), //
        new SectionListItem("Test 19 - B again", "B"), //
        new SectionListItem("Test 20 - B again", "B"), //
        new SectionListItem("Test 21 - B again", "B"), //
        new SectionListItem("Test 22 - B again", "B"), //
        new SectionListItem("Test 23 - C", "C"), //
        new SectionListItem("Test 24 - C", "C"), //
        new SectionListItem("Test 25 - C", "C"), //
        new SectionListItem("Test 26 - C", "C"), //
};

private StandardArrayAdapter arrayAdapter;

private SectionListAdapter sectionAdapter;

private SectionListView listView;

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    arrayAdapter = new StandardArrayAdapter(this, R.id.example_text_view,
            exampleArray);
    sectionAdapter = new SectionListAdapter(getLayoutInflater(),
            arrayAdapter);
    listView = (SectionListView) findViewById(getResources().getIdentifier(
            "section_list_view", "id",
            this.getClass().getPackage().getName()));
    listView.setAdapter(sectionAdapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.test_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.standard_list:
        arrayAdapter = new StandardArrayAdapter(this,
                R.id.example_text_view, exampleArray);
        sectionAdapter = new SectionListAdapter(getLayoutInflater(),
                arrayAdapter);
        listView.setAdapter(sectionAdapter);
        return true;
    case R.id.empty_list:
        arrayAdapter = new StandardArrayAdapter(this,
                R.id.example_text_view, new SectionListItem[] {});
        sectionAdapter = new SectionListAdapter(getLayoutInflater(),
                arrayAdapter);
        listView.setAdapter(sectionAdapter);
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

}

The problem is the following:

When I check a checkbox and scroll down or up, another, previously not checked checkbox is getting checked. I think it is a problem with the getView type, but do not know how to fix this.

venni
  • 594
  • 1
  • 4
  • 19

1 Answers1

2

As I understand it, your list item has a TextView and a CheckBox. In getView, you are only setting the TextView, and the CheckBox is set by the user.

The cells of a list view get reused, so when the user checks one and scrolls down, eventually the same cell with the checked CheckBox will reappear. For instance, let's say you have 3 cells visible at any time. To start, you have A,B,C on screen, and the user clicks on A. As the user scrolls, the system might create a new cell, D, and then reuse A. So you could have a situation where C,D,A are now on screen. A still has its CheckBox checked, because it was never reset. To prevent this, you should explicitly track and set the state of the CheckBox in getView().

For instance, you could add a boolean to SectionListItem that keeps track of the checked state. You will set the boolean, isChecked when the user clicks on the CheckBox, and then in getView(), you will set the CheckBox according to the boolean in currentItem.

Checkbox checkbox =  (CheckBox) view.findViewById(R.id.example_checkbox);
checkbox.setChecked(currentItem.getIsChecked());

or, if currentItem.getIsChecked() returns an integer:

checkbox.setChecked(currentItem.getIsChecked() != 0);
GLee
  • 5,003
  • 5
  • 35
  • 39
  • Thats right. The checkbox will be set by the user. Then another checkbox is getting checked also when I scroll down or up. I do not understand what you mean with tracking he state. Has it something to do with the "getItemViewType" and "getViewTypeCount" methods from this topic? http://stackoverflow.com/questions/5300962/getviewtypecount-and-getitemviewtype-methods-of-arrayadapter But I do not know how to do it for this example... – venni Dec 10 '13 at 23:34
  • See my edit, I've fleshed out the explanation a little bit more. Let me know if you need any more clarification. – GLee Dec 10 '13 at 23:45
  • I understand what the problem is. Thanks for describing it. I stored a string in the item, but with the same problem: if (currentItem.todo_done.toString().equalsIgnoreCase("1")){ checkBox.setChecked(true); } – venni Dec 11 '13 at 00:06
  • Ummm, why are you doing .equalsIgnoreCase("1), instead of just using a boolean? Check to make sure that your if statement is actually doing what you think it is. – GLee Dec 11 '13 at 02:10
  • In my code I am storing the value if a checkbox is checked or not in a SQLite DB. That is the flag that I am checking if it is "1" and then mark the checkbox as checked or not. But I think the problem is that the value for the flag in currentItem is not changed in the getView() method. It is reused and giving me the same value. – venni Dec 11 '13 at 06:45
  • You should use a boolean instead of a string as a flag. That's what they are for. If you set the boolean in the onClickListener, read it in getView, and get rid of the .equalsIgnoreCase(), your code should work. – GLee Dec 11 '13 at 06:52
  • SQLite does not have a separate Boolean storage class. Instead, Boolean values are stored as integers 0 (false) and 1 (true). In my case it is a string. Netvertheless even if I use an integer for that, I have to compare to 0 or 1 and make a decision if true or false like I already done with a string. – venni Dec 11 '13 at 07:34
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/42978/discussion-between-glee-and-venni) – GLee Dec 11 '13 at 18:53