滚动视图时,Android ListView会丢失复选框的状态

时间:2014-05-25 02:18:17

标签: android listview

我已经设法让我的应用程序在更改复选框的状态时更新我的​​数据库,但是当我滚动我的应用程序时,复选框的状态会发生变化。

我的问题是:如何保存复选框的状态,以便在滚动视图时它们不会改变?

这是我的光标适配器。

public CustomCursorAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
     mInflater = (LayoutInflater) 
             context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    View view = mInflater.inflate(R.layout.wildlifelist, parent, false);
    ViewHolder holder = new ViewHolder();

    holder.img = (ImageView) view.findViewById(R.id.img); 
    holder.mname = (TextView) view.findViewById(R.id.maori);   
    holder.name = (TextView) view.findViewById(R.id.name);    
    holder.status = (TextView) view.findViewById(R.id.status);
    holder.check = (CheckBox) view.findViewById(R.id.check);

    view.setTag(holder);    
    return view;    
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    ViewHolder holder = (ViewHolder) view.getTag();

    final long rowId = cursor.getLong(cursor.getColumnIndex(DBhelper.KEY_ID));

    byte[] img = cursor.getBlob(cursor.getColumnIndex(DBhelper.KEY_IMG));
    holder.img.setImageBitmap(BitmapFactory.decodeByteArray(img, 0, img.length));

    holder.mname.setText(cursor.getString(cursor.getColumnIndex(DBhelper.KEY_MNAME)));
    holder.name.setText(cursor.getString(cursor.getColumnIndex(DBhelper.KEY_NAME)));
    holder.status.setText(cursor.getString(cursor.getColumnIndex(DBhelper.KEY_STATUS)));

    holder.check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {   
            if (isChecked) {        
                Log.w("Debug","RowID: " + rowId + ", isChecked: " + isChecked); 
                DBhelper.updateRow(rowId, 1);
            }
            else {
                Log.w("Debug","RowID: " + rowId + ", isChecked: " + isChecked);
                DBhelper.updateRow(rowId, 0);
            }   
        }
    });
}

public static class ViewHolder {
    ImageView img;
    TextView mname;
    TextView name;
    TextView status;
    CheckBox check;
} 

2 个答案:

答案 0 :(得分:0)

ListView在滚动时重用行。 BindView()方法可以为您提供一行(可能正在重复使用),并允许您根据光标对象的属性进行设置。看起来你没有在BindView()中设置holder.check,这可能是滚动ListView时它们不正确的原因。

答案 1 :(得分:0)

使用arraymap绑定视图中每个项目的检查状态。代码应该看起来像这样。

CustomCursorAdapter extends CursorAdapter{

    Map<Long, Boolean> checkState = new HashMap<>();

    public CustomCursorAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
         mInflater = (LayoutInflater) 
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ViewHolder holder = (ViewHolder) view.getTag();

         ///set other views

         holder.check.setOnCheckedChangeListener(null); //unregister the check listener

         //I like to assume all views are unchecked by default
         Boolean checked = checkState.get(rowId);
         checked = (checked == null ? false : checked);

         holder.check.setChecked(checked);

        holder.check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {   
                //save the check state
                checkState.put(rowId, isChecked);

                if (isChecked) {        
                    Log.w("Debug","RowID: " + rowId + ", isChecked: " + isChecked); 
                    DBhelper.updateRow(rowId, 1);
                }
                else {
                    Log.w("Debug","RowID: " + rowId + ", isChecked: " + isChecked);
                    DBhelper.updateRow(rowId, 0);
                }   
            }
        });
    }
}