2

enter image description here

Above shown is my custom listview with TextViews and RadioGroup. Based on whether the item status is "pending" or "served" I update the pending items-TextView (in red, on top). Everything is working as expected, and I am able to retain the RadioGroup selections on scroll.

However, when I scroll, the pending Items TextView does not retain its value. It changes whenever the list scrolls. Here is my getView method.

public View getView(final int position, View convertView, ViewGroup parent) 
{
    System.out.println(" --- position ---"+position+" --- isChecked[position] --- "+isChecked[position]);

    ViewHolder viewHolder = null;
    if(convertView == null)
    {

        convertView = layoutInflater.inflate(R.layout.order_status_listview_row, null);
        viewHolder = new ViewHolder();
        convertView.setTag(viewHolder);
    }
    else
    {
        viewHolder = (ViewHolder)convertView.getTag();
        convertView.setTag(viewHolder);
    }

    viewHolder.itemName = (TextView)convertView.findViewById(R.id.textview_order_status_item_name);
    viewHolder.itemQuantity = (TextView)convertView.findViewById(R.id.textview_order_status_item_quantity);
    viewHolder.radioGroup = (RadioGroup)convertView.findViewById(R.id.radiogroup_order_status_dialog);

//      isUserChanged[position] = false;
    viewHolder.radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() 
    {           
        public void onCheckedChanged(RadioGroup group, int checkedId) 
        {
 //             if(isUserChanged[position])
            {
                switch(checkedId) 
                {
                    case R.id.radiobutton_served:
                         System.out.println(" --- radiobutton_served ---"+" position "+position+" isChecked[position] "+isChecked[position]);
                         count--;
 //                          countView.setText(DataHelper.getAppropriateCountValue(count));
                         isChecked[position] = true;
                         break;

                    case R.id.radiobutton_pending:
                         System.out.println(" --- radiobutton_pending ---"+" position "+position+" isChecked[position] "+isChecked[position]);
                         isChecked[position] = false;
                         count++;
 //                          countView.setText(DataHelper.getAppropriateCountValue(count));
                         break;             
                }
                countView.setText(DataHelper.getAppropriateCountValue(count));

            }
 //             isUserChanged[position] = false;
        }
    });

    viewHolder.radioGroup.setOnClickListener(new OnClickListener() 
    {
        public void onClick(View view) 
        {
 //             isUserChanged[position] = true;
        }
    }); 

    viewHolder.itemName.setText(orderList.get(position).getDishName());
    viewHolder.itemQuantity.setText(orderList.get(position).getDishQuantity());

    // change selection state for item checked when selection for radioButton changes
    if(isChecked[position])
        viewHolder.radioGroup.check(R.id.radiobutton_served);
    else
        viewHolder.radioGroup.check(R.id.radiobutton_pending);

    return convertView;
}
pixelscreen
  • 1,945
  • 2
  • 18
  • 40
  • 2
    Please put the findViewById methods in the if(convertView == null), or your viewHolder is useless. – AMerle Jul 24 '12 at 07:26
  • @PareshMayani it's not a duplicate. I have already solved the problem mentioned in that link. – pixelscreen Jul 24 '12 at 07:30
  • @CFlex done, thanks! but what abt the problem mentioned in this question? – pixelscreen Jul 24 '12 at 07:31
  • Try not to use viewHolder.radioGroup.check(R.id.radiobutton_served); but save your radiobuttons in your viewholder then viewHolder.radiobutton1.setchecked(true); or something like this. not sur it gonna work... – AMerle Jul 24 '12 at 07:31
  • I posted an answer, just ignore my comment :p – AMerle Jul 24 '12 at 07:48

2 Answers2

5

Dya, I made a small example.

My Activity contains a TextView and a ListView. The ListView is filled with 20 objects (RowObject) which have their own layout (row.xml). The code is pretty straight forward so you will have no problem reading it and understanding it.

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/mTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0" />

    <ListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/mTextView" >
    </ListView>

</RelativeLayout>

row.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RadioGroup
        android:id="@+id/mRadioGroup"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <RadioButton
            android:id="@+id/mRadio1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="radio1" />

        <RadioButton
            android:id="@+id/mRadio2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="radio2" />
    </RadioGroup>

</LinearLayout>

RowObject

public class RowObject {

    private int ID;
    private boolean firstChecked; // else second checked

    public RowObject(int iD, boolean firstChecked) {
        super();
        ID = iD;
        this.firstChecked = firstChecked;
    }

    public boolean isFirstChecked() {
        return firstChecked;
    }

    public void setFirstChecked(boolean firstChecked) {
        this.firstChecked = firstChecked;
    }
}

MainActivity

public class MainActivity extends Activity {

    private TextView mCountTextView;
    private ArrayList<RowObject> mSource;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSource = new ArrayList<RowObject>();
        for (int i = 0; i < 20; i++) {
            mSource.add(new RowObject(i, false));
        }

        mCountTextView = (TextView) findViewById(R.id.mTextView);

        ListView mListView = (ListView) findViewById(R.id.mListView);
        mListView.setAdapter(new RadioButtonAdapter(getApplicationContext(), mSource));
    }

    private class RadioButtonAdapter extends ArrayAdapter<RowObject> {

        class ViewHolder {
            RadioGroup rbGroup;
            RadioButton btn1;
            RadioButton btn2;
        }

        private LayoutInflater mInflater;

        public RadioButtonAdapter(Context context, ArrayList<RowObject> mSource) {
            super(context, R.layout.row, mSource);
            mInflater = LayoutInflater.from(context);
        }

        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder;

            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.row, null);

                holder = new ViewHolder();
                holder.rbGroup = (RadioGroup) convertView.findViewById(R.id.mRadioGroup);
                holder.btn1 = (RadioButton) convertView.findViewById(R.id.mRadio1);

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

            holder.rbGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    switch (checkedId) {
                    case R.id.mRadio1:
                        mSource.get(position).setFirstChecked(true);
                        break;

                    case R.id.mRadio2:
                        mSource.get(position).setFirstChecked(false);
                        break;
                    }
                    mCountTextView.setText("There are " + getNumberOfFirstCheckedViews() + " first buttons selected");
                }
            });

            if (mSource.get(position).isFirstChecked()) {
                holder.btn1.setChecked(true);
                holder.btn2.setChecked(false);
            } else {
                holder.btn1.setChecked(false);
                holder.btn2.setChecked(true);
            }

            return convertView;
        }

        private int getNumberOfFirstCheckedViews() {
            int count = 0;
            for (RowObject object : mSource) {
                if (object.isFirstChecked()) {
                    count++;
                }
            }
            return count;
        }
    }
}
DroidBender
  • 7,762
  • 4
  • 28
  • 37
  • CFlex's solution worked. Thanks a lot for your time though Martijn :) – pixelscreen Jul 24 '12 at 10:47
  • It's work fine, @DroidBender when i check any radio button then i want to open or switch another activity so where i can set onclicklistener ? please possible then help me – Farmer Oct 19 '16 at 08:25
  • When i try to set in adapter and click one radio button it's fine but problem is when i scroll the listview then it automatically called after every 10 row scrolled – Farmer Oct 19 '16 at 08:44
4

I think I got it. Whenever you scroll, you change the values or your radiobuttons with your

if(isChecked[position])
    viewHolder.radioGroup.check(R.id.radiobutton_served);
else
    viewHolder.radioGroup.check(R.id.radiobutton_pending);

But you set a listener BEFORE you call that. So the listener is called each time.

Try this instead:

viewHolder.radioGroup.setOnCheckedChangeListener(null);

if(isChecked[position])
    viewHolder.radioGroup.check(R.id.radiobutton_served);
else
    viewHolder.radioGroup.check(R.id.radiobutton_pending);

viewHolder.radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() 
    {           
        public void onCheckedChanged(RadioGroup group, int checkedId) 
        {
 //             if(isUserChanged[position])
            {
                switch(checkedId) 
                {
                    case R.id.radiobutton_served:
                         System.out.println(" --- radiobutton_served ---"+" position "+position+" isChecked[position] "+isChecked[position]);
                         count--;
 //                          countView.setText(DataHelper.getAppropriateCountValue(count));
                         isChecked[position] = true;
                         break;

                    case R.id.radiobutton_pending:
                         System.out.println(" --- radiobutton_pending ---"+" position "+position+" isChecked[position] "+isChecked[position]);
                         isChecked[position] = false;
                         count++;
 //                          countView.setText(DataHelper.getAppropriateCountValue(count));
                         break;             
                }
                countView.setText(DataHelper.getAppropriateCountValue(count));

            }
 //             isUserChanged[position] = false;
        }
    });

Hope this will help you.

AMerle
  • 4,354
  • 1
  • 28
  • 43
  • 1
    I didn't know such a small thing would fix this! u gave me a soln to a problem which I spent 2 days on! Thanks a ton :) – pixelscreen Jul 24 '12 at 10:51