简体   繁体   中英

Android listview mixes rows when scrolling

Okay, I gave it up now, plese help me guys.

I saw that the net is full of questions like mine. But none of them helped me, because 90% of the questions make a simple mistake, eg put the setting methods into the if statement.

I think I know the basics, don't do simple mistakes and still it's not working.

I have a ListView, and in every row I have a TextView and four RadioButton. You can set one of them in each row. Thats simple. I use ViewHolder for smooth scrolling, because there are a few hundred rows in the list. And when you start scrolling, it screws everything: checked RBs getting unchecked and vica versa.

The joke is, that this is (only) a visual error, because when is save the settings, only the rows are actually touched are in checked state, so basicly it works, but I can't tell my users to ignore what u see :)

I tried everything with that code, where is the error?

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

    // i need a final modifier because I use the holder in Listener
    final ViewHolder holder;

    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.hatranyos_lista_row, parent, false);
        holder = new ViewHolder();

        holder.nev = (TextView) convertView.findViewById(R.id.nev);
        holder.rg = (RadioGroup) convertView.findViewById(R.id.radioTipus);
        holder.rb_elit = (RadioButton) convertView.findViewById(R.id.radioElit);
        holder.rb_atl = (RadioButton) convertView.findViewById(R.id.radioAtlagos);
        holder.rb_atl_a = (RadioButton) convertView.findViewById(R.id.radioAtlagAlatt);
        holder.rb_rossz = (RadioButton) convertView.findViewById(R.id.radioRossz);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    // one listener for the RadioGroup. I think its okay, because when i remove it, my problem still exists
    holder.rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            if (holder.rb_elit.isChecked()) {
                values.get(position).setH_statusz(1);
            }
            if (holder.rb_atl.isChecked()) {
                values.get(position).setH_statusz(2);
            }
            if (holder.rb_atl_a.isChecked()) {
                values.get(position).setH_statusz(3);
            }
            if (holder.rb_rossz.isChecked()) {
                values.get(position).setH_statusz(4);
            }
        }
    });

    // setters after the if statement
    holder.nev.setText(values.get(position).getUtvonal() + "/" + values.get(position).getPos() + " " + values.get(position).getNev());

    int h_statusz = values.get(position).getH_statusz();

    // and finally (pre)setting the RBs. I know rows will recycle so I tried to set in every case
    switch (h_statusz) {
    case 1:
        holder.rb_elit.setChecked(true);
        holder.rb_atl.setChecked(false);
        holder.rb_atl_a.setChecked(false);
        holder.rb_rossz.setChecked(false);
        break;
    case 2:
        holder.rb_elit.setChecked(false);
        holder.rb_atl.setChecked(true);
        holder.rb_atl_a.setChecked(false);
        holder.rb_rossz.setChecked(false);
        break;
    case 3:
        holder.rb_elit.setChecked(false);
        holder.rb_atl.setChecked(false);
        holder.rb_atl_a.setChecked(true);
        holder.rb_rossz.setChecked(false);
        break;
    case 4:
        holder.rb_elit.setChecked(false);
        holder.rb_atl.setChecked(false);
        holder.rb_atl_a.setChecked(false);
        holder.rb_rossz.setChecked(true);
        break;
    default:
        holder.rb_elit.setChecked(false);
        holder.rb_atl.setChecked(false);
        holder.rb_atl_a.setChecked(false);
        holder.rb_rossz.setChecked(false);
        break;
    }

    return convertView;
}

static class ViewHolder {
    TextView nev;
    RadioGroup rg;
    RadioButton rb_elit;
    RadioButton rb_atl;
    RadioButton rb_atl_a;
    RadioButton rb_rossz;
}

First, unset the OnCheckedChangeListener from your RadioGroup. Then set the check state of each button. Finally register a new OnCheckedChangeListener at the end.

I'm guessing that when you set the check state of items after setting the listener on the group, the listener is getting invoked each time.

Finally - the only thing that worked - I dropped out the ViewHolder. I modified my Activity and the list contains not a few hundreds but only 10-20 rows and with this low number of rows scrolling remains smooth without the ViewHolder. If I use it that bug is there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM