1

I'm trying to implement a custom array adaptor that has to visualise a list view with one text and one checkbox. I need to remember the selection and I want that every time one option is chececked all the others become unchecked as a radiobutton.

This is my code

public class RAnswerAdapter extends ArrayAdapter<RAnswer> {

private final ArrayList<RAnswer> list;
private final Activity context;

public RAnswerAdapter(Activity context, ArrayList<RAnswer> list) {
    super(context, R.layout.answer_item, 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;
    if (convertView == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.answer_item_radio, null);
        final ViewHolder viewHolder = new ViewHolder();
        viewHolder.text = (TextView) view.findViewById(R.id.answerName);
        viewHolder.checkbox = (CheckBox) view.findViewById(R.id.checkAnsw);

        viewHolder.checkbox
                .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                            boolean isChecked) {
                        Answer element = (Answer) viewHolder.checkbox.getTag();

                        for(Answer a: list)
                            //if true
                            if(a.isSelected())
                                //I set at false
                                a.setSelected(false);

                        //I set the new at true
                        element.setSelected(buttonView.isChecked());    

                        //I refresh the list
                        notifyDataSetChanged();
                    }
                });



        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).getAnswer_option());
    holder.checkbox.setChecked(list.get(position).isSelected());
    return view;
}

}

The code actually works in a strange way... The first 4 element of the list work perfectly and all the others aren't checkable! Why this? Where is the error?

Thanks for the help

michoprogrammer
  • 1,159
  • 2
  • 18
  • 45
  • Are the first four elements the only visible elements? ie The error happens when you scroll to a row and check that box? – Sam May 11 '12 at 21:53
  • Also, please post the logcat errors otherwise we just have to guess... – Sam May 11 '12 at 21:54
  • If there are less then four elements the error happens only on the first (ex: there are 3 elements and it works only on the first 2 elements). They aren't the only visible. Usually I can see at least 8 elements. I know that is very strange! In the logcat there are no errors! – michoprogrammer May 14 '12 at 14:40

2 Answers2

0

I think that you have to look at this useful post on here StackOverflow. If you take a look there is a link to a tutorial that I have made and that can be the solution to your problem ;)

Link CheckedListView

Community
  • 1
  • 1
Simone Casagranda
  • 1,217
  • 17
  • 26
  • Grazie Simone =) I know how to implement a listview as you implemented in your tutorial. The problem is that I'm trying to create a listview to handle a single choice and not a multiple choice. – michoprogrammer May 14 '12 at 14:46
  • Fine :) If you don't use multi-choice, it's better if you use radio and not checkbox to allow user selection. So I think that you can simply use the based proposed solution inside the sdk. You have to set the type of selection into your listview with the following line: listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE); – Simone Casagranda May 14 '12 at 15:10
  • There are two problems using the solution that you proposed: 1) The designer requested that the radiobuttons are equal to the checkboxes. (Square and not circle :/ ) 2) With the "ListView.CHOICE_MODE_SINGLE", I can't save the state of the selected items (or maybe it's possible but I don't know how to do). So I passed to implement it with the checkboxes... – michoprogrammer May 14 '12 at 15:21
  • Mmm with single mode you can choose only one element, not more than one. However there is a method that allows you to get the checked ids and if I'm not saying a wrong notice is precisely listview.getCheckedIds and returns a long array :) – Simone Casagranda May 14 '12 at 21:54
  • Aahaha qualcuno qui sa troppo bene l'italiano :) – Simone Casagranda May 15 '12 at 22:04
0

I am having trouble pinpointing the problem in your code without being able to debug it myself. I'll suggest adding a variable to your adapter to store the index of the currently checked item, this way you do not have to search list on every click. Also add an if statement in your onCheckChanged() to not take action if the answer is already checked (like it seems to behave now) or even allow the user to uncheck the current answer.

To push the ChoiceMode option of a ListView myself, I'll present this:

public class Example extends Activity implements OnItemClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String[] array = {"one", "two", "three"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, array);

        ListView listView = (ListView) findViewById(R.id.list);
        listView.setAdapter(adapter);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setOnItemClickListener(this);
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Log.v("Example", "ItemClick: " + ((ListView) parent).getCheckedItemPosition());
    }
}

This app is short and sweet. You can design your own layout and pass it to the adapter, here is the current checkbox example. And you can reference the position (or id or text) of the checked row at any point; even save all the answers in a database as you go.

Let me know if either of these help.

Sam
  • 86,580
  • 20
  • 181
  • 179
  • The problem it was in the viewholder that didn't refresh my list, so I tried to implemented it in the oldest way, without any static class and it works well! I know that isn't the best solution, but this particular listview is a particular case of my app and at most there are 10 element, so I think that there aren't too many memory problem. If in the test phase I'll encounter some problems, I'll try your way. Thanks to anybody. – michoprogrammer May 14 '12 at 20:50