【问题标题】:Android ListView losing state of check boxes when view is scrolled [duplicate]滚动视图时,Android ListView失去复选框的状态[重复]
【发布时间】:2014-05-25 02:18:16
【问题描述】:

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

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

这是我的光标适配器。

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

【问题讨论】:

    标签: android listview


    【解决方案1】:

    使用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);
                    }   
                }
            });
        }
    }
    

    【讨论】:

    • 我尝试了您的建议,但仍然存在复选框丢失状态的问题。我不得不将 Cursor cursor 更改为 final Cursor cursor 因为我无法引用游标,因为它是 onCheckedChanged 方法中的非最终变量,这可能是导致此问题的原因吗?
    • @FusionFox 我建议您分享完整的代码,以便我检查故障。如果太大,使用 pastebin 或 sth
    • @FusionFox 再想一想,如果光标在连接到适配器时没有完全加载,那么可能是原因。在这种情况下, Map 会更好。因此您可以跟踪每个行 id 的检查状态
    • 我将如何实施地图
    • @FusionFox 我用地图改了答案,看看
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多