6

I am creating a android app the UI of my application is below given.

On clicking of submit button, I need the selected check box, and radio buttons value.

Example Linux is not checked, cc(radio button) is checked.

Records are populated dynamically in list view, but I am not able to make it work. A lot of problems are there.

  1. When I scroll the list view radio button gets automatically selected or deselected not able to maintain the state of radio button.
  2. On click of button not getting the selected radio button as well as check box.

Below is my layout as well as java program. Suggest me to get the correct values.

application image

Main.xml

<ListView
    android:id="@+id/my_list"
    android:layout_width="fill_parent"
    android:layout_height="199dp" />

<Button
    android:id="@+id/submit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    />

row.xml

<TextView
    android:id="@+id/label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:layout_toRightOf="@+id/check"
    android:textSize="20sp" >
</TextView>

<CheckBox
    android:id="@+id/check"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_marginLeft="4dip"
    android:layout_marginRight="10dip"
    android:focusable="false"

    android:focusableInTouchMode="false" >
</CheckBox>

 <RadioGroup
     android:id="@+id/radioSex"
     android:layout_width="wrap_content"
     android:layout_height="fill_parent"
     android:layout_alignParentRight="true"
     android:layout_alignParentTop="true"
     android:orientation="horizontal" >

     <RadioButton
         android:id="@+id/to"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginLeft="10dip"
         android:checked="true"
         android:text="To" />

     <RadioButton
         android:id="@+id/cc"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginLeft="10dip"
         android:text="CC" />
 </RadioGroup>

MyAdaptor.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();
                            list.get(getPosition).setSelected(
                                    buttonView.isChecked());
                        }
                    });
            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);

        viewHolder.text.setText(list.get(position).getName());
        viewHolder.checkbox.setChecked(list.get(position).isSelected());

        return convertView;
    }

MainActivity.java

public class MainActivity extends Activity implements OnItemClickListener {

    ListView listView;
    ArrayAdapter<Model> adapter;
    List<Model> list = new ArrayList<Model>();

    private RadioGroup radioCcToGroup;
    private RadioButton radioTypeButton;
    private Button btn;

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);

        listView = (ListView) findViewById(R.id.my_list);

        btn = (Button) findViewById(R.id.submit);

        btn.setOnClickListener(new View.OnClickListener() {
            int count = 0;

            @Override
            public void onClick(View view) {


                count = listView.getAdapter().getCount();
                for (int i = 0; i < count; i++) {
                    // here i am not able to get the records as getting on onItemClick of the listview
                }
            }
        });

        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;
    }

Model.java

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;
    }
Pat Needham
  • 5,698
  • 7
  • 43
  • 63
subodh
  • 6,136
  • 12
  • 51
  • 73

1 Answers1

8

You got 2 mistakes here both on your MyAdaptor.java :

  1. When you attach the onCheckedChangeListener you do it only when a new view needs to be created and you forget the case where the list view reuses the view. You should setOnCheckedChangeListener outside if (convertView == null).

  2. It seems that onCheckedChangeListener is called also when the scroll is done (because of viewHolder.checkbox.setChecked(list.get(position).isSelected());). You can avoid this by using OnClickListener over viewHolder.checkbox or not calling viewHolder.checkbox.setChecked().

Here is my code:

private class ViewHolder {
    protected TextView text;
    protected CheckBox checkbox;
    protected RadioGroup radioGroup;
}

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;
    }

    @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.setTag(position);
            viewHolder.radioGroup = (RadioGroup) convertView.findViewById(R.id.radioSex);
            viewHolder.radioGroup.setTag(position);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.text.setText(list.get(position).getName());
        viewHolder.checkbox.setChecked(list.get(position).isSelected());
        viewHolder.checkbox.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                CheckBox checkbox = (CheckBox) v;
                int getPosition = (Integer) checkbox.getTag();
                list.get(getPosition).setSelected(checkbox.isChecked());
            }
        });

        viewHolder.radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                boolean isCcOrIsTo = (checkedId == R.id.cc);
                int getPosition = (Integer) group.getTag();
                list.get(getPosition).setCcOrIsTo(isCcOrIsTo);
            }
        });

        return convertView;
    }
}

Notice i've added some control over the radiogroup too, so Model.java has changed:

public class Model {

    private String name;
    private boolean selected;
    private boolean isCcOrIsTo;

    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;
    }

    public boolean isCcOrIsTo() {
        return isCcOrIsTo;
    }

    public void setCcOrIsTo(boolean isCcOrIsTo) {
        this.isCcOrIsTo = isCcOrIsTo;
    }

    @Override
    public String toString() {
        String selectedString = selected ? "selected" : "not selected";
        String value = isCcOrIsTo ? "CC" : "To";
        return name+" -> "+selectedString+ " with value "+value;
    }
}

Finally you don't need onItemClick on MainActivity.java, to check if the values are correct when you click the summit button :

public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.activity_main);

    listView = (ListView) findViewById(R.id.my_list);

    btn = (Button) findViewById(R.id.submit);

    btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            for (Model m : list) {
                Log.i("Stack1", m.toString());
            }
        }
    });

    ArrayAdapter<Model> adapter = new MyAdapter(this, getModel());
    listView.setAdapter(adapter);
}

Hope it helps ;)

Kalem
  • 1,132
  • 12
  • 33
  • Thanks, @Kalem, but still if I scroll the listview it gets automatically selected. If i don't select any radio button option and then scrolling is not effecting but, in case if do select any one of them. – subodh Sep 27 '12 at 05:31
  • Weird, i didn't had that problem when i tested, i'll take a look at that once more. Just to be clear, did you replace the `setOnCheckedChangeListener`? You can also checkout if it doesn't come from : `viewHolder.checkbox.setChecked(list.get(position).isSelected());` – Kalem Sep 27 '12 at 05:52
  • I just copy and paste your code but in case of check box it works fine even I got all the response correctly. but when i select any one of radio button and scroll, it select more than one radio button in UI but when I submit the page it show only which is expected but in UI is shows multiple as checked. – subodh Sep 27 '12 at 05:58
  • It showing more than one as selected in UI only in case of radio button, while in submit of button it response only which I selected. – subodh Sep 27 '12 at 06:01
  • Still not able to reproduce on Gingerbread nor ICS. Check your not doing adding a listener before you set the state of the radioGroup `viewHolder.radioGroup.check();` (if your are). If my answer did help you plz check it ;) – Kalem Sep 27 '12 at 09:20
  • thanks and +1 for you support, but still struggling with the issue. – subodh Sep 27 '12 at 09:49
  • @subodh I am facing same problem,can you please update how did you solve this issue. – Dory Jul 19 '13 at 07:51
  • are you doing the same thing proposed by Kalem? – subodh Jul 19 '13 at 08:37
  • @Kalem: I have the very same problems. With your `.getTag()` method I get the very same recycled position, not the 'true' position. So I don't see why this would be a solution...? Android is extremely frustrating sometimes. :( – Luis A. Florit Oct 19 '13 at 23:19
  • @LuisA.Florit did you do the `viewHolder.radioGroup.setTag(position);` on the `public View getView(int position, View convertView, ViewGroup parent)` method? – Kalem Oct 28 '13 at 12:01
  • @Kalem: Yes. But never mind, I found a mistake in my code and solve the problem without the tags. Thanks! – Luis A. Florit Oct 28 '13 at 15:56