Automatic selection of checkboxes inside listview

2019-04-02 13:37发布

I am building a list and the list contain for every contact a checkbox to chose which one to modify for example, the problem is that when the list became longer than the phone screen and the scrolling is active; when i select a check box , a second one is automatically selected in the bottom of the list.

the problem is the automatic selection of the second checkbox; please let me know how can i fix it ??

below is the code i am using for getView method

   public View getView(int position, View converView, ViewGroup parent){


   View row = converView;
   if(row == null){
   LayoutInflater inflater = getLayoutInflater();
   row = inflater.inflate(R.layout.edit, parent, false);
   }

   TextView label = (TextView)row.findViewById(R.id.label);
   label.setText(items[position]);

   CheckBox cb = (CheckBox)row.findViewById(R.id.del);

   ImageView icon = (ImageView)row.findViewById(R.id.icon);
   icon.setImageResource(images.get(position));

   Log.i("Pos", ""+position);


   return row;   
  } 
}

4条回答
Deceive 欺骗
2楼-- · 2019-04-02 13:53
劫难
3楼-- · 2019-04-02 13:54

Works fine for me

public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        final ViewHolder holder;
        final Season season = (Season) getGroup(groupPosition);
        if (convertView == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.season, parent, false);
            holder = new ViewHolder();
            holder.title = (TextView) convertView.findViewById(R.id.season_title);
            holder.checkBox = (CheckBox) convertView.findViewById(R.id.season_check_box);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.title.setText(season.getTitle());
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                season.setChecked(isChecked);
                adapter.notifyDataSetChanged();
            }
        });

        holder.checkBox.setChecked(season.isChecked()); // position is important! Must be before return statement!
        return convertView;
    }

    protected class ViewHolder {
        protected TextView title;
        protected CheckBox checkBox;
    }
查看更多
看我几分像从前
4楼-- · 2019-04-02 13:56

Yyou can also use a SparseBooleanArray which allows you to use the list position as the key

查看更多
爷的心禁止访问
5楼-- · 2019-04-02 14:13

The problem is that list reuses your view (hence the convertView argument in getView). In your code, if you get a convertView that isn't null, you have to change its checkbox checked state to what is relevant for the new content.

Let's say view1 is first associated with id 1 and you check it. Then, you scroll and view1 is converted to display id 10. But since the view isn't recreated, it will still have the checkbox state from the item with id 1.

So basically the solution is to store somewhere which items are selected and in our getView method, you would do

cb.setChecked(isItemChecked(position));

And you have to implement isItemChecked(int position);

An inefficient but working implementation would be to use an array of boolean in your activity, let's say

boolean[] itemChecked;

And then in getView, you set a listener on checkbox checked (have to make position final for this to work). You also set the checked state using the array.

cb.setOnCheckedChangeListener (new OnCheckedChangeListener () {
  public void onCheckedChanged (CompoundButton btn, boolean isChecked) {
    itemChecked[position] = isChecked;
  }
});

cb.setChecked(itemChecked[position]);

But again, using an array for that is maybe not the most efficient implementation, especially if you have a huge number of elements in your list.

查看更多
登录 后发表回答