Android:光标适配器、列表视图和复选框

8xiog9wr  于 2022-11-27  发布在  Android
关注(0)|答案(8)|浏览(107)

我有自己的布局和CustomCursorAdapter的ListView。每一行都有自己的复选框。所以......很明显,在滚动过程中,复选框会失去它们的状态。我找到的唯一东西是Android save Checkbox State in ListView with Cursor Adapter,但那里没有答案。还有一个问题。我的CustorArrayAdapter也有同样的问题。我使用SparseBooleanArray来保持复选框的状态,解决了这个问题。它工作得很好。但每次滚动都会调用onCheckedChanged。这正常吗?问题是我的列表视图描述了警报元素,并且定期调用(onCheckedChanged的)启动/停止警报。很多不必要的操作。

bvn4nwqk

bvn4nwqk1#

我的ListViewCheckBox也有类似的问题,我做了什么来摆脱这个问题:

  • 创建一个Boolean Object的ArrayList来存储每个CheckBox的状态
  • 将ArrayList项初始化为默认值false,表示尚未选中CheckBox。
  • 当你点击CheckBox时,设置一个Checked/Unchecked状态的检查,并将该值存储在ArrayList中。
  • 现在,使用setChecked()方法将该位置设置为CheckBox。

请参阅以下代码片段:

public class DataAdapter extends SimpleCursorAdapter {
private Cursor c;
private Context context;
private ArrayList<String> list = new ArrayList<String>();
private ArrayList<Boolean> checkedItems = new ArrayList<Boolean>();

public DataAdapter(Context context, int layout, Cursor c, String[] from,
        int[] to) {
    super(context, layout, c, from, to);
    this.c = c;
    this.context = context;

    for (int i = 0; i < this.getCount(); i++) {
        checkedItems.add(i, false); // initializes all items value with false
    }
}

public View getView(final int pos, View inView, ViewGroup parent) {
    if (inView == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inView = inflater.inflate(R.layout.list_item, null);
    }

    final CheckBox checkBox = (CheckBox) inView.findViewById(R.id.bcheck);
    checkBox.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            CheckBox cb = (CheckBox) v;
            if (cb.isChecked()) {
                checkedItems.set(pos, true);
            } else if (!cb.isChecked()) {
                checkedItems.set(pos, false);
            }
        }
    });
    checkBox.setChecked(checkedItems.get(pos));
    return inView;
}}
zhte4eai

zhte4eai2#

当列表视图中有可检查的项时,有一些问题。我建议使用以下链接:
http://tokudu.com/2010/android-checkable-linear-layout/
我觉得这和你想要的很接近。

pgx2nnw8

pgx2nnw83#

我也面临着类似的问题,所以经过大量的阅读我解决了这个问题这样:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.listview, null);
            holder = new ViewHolder();
            holder.nameView = (TextView)convertView.findViewById(R.id.textView1);
            holder.numberView = (TextView)convertView.findViewById(R.id.textView2);
            holder.cb = (CheckBox)convertView.findViewById(R.id.checkBox1);
            convertView.setTag(holder);                
        } else {
            holder = (ViewHolder)convertView.getTag();
        }
        holder.nameView.setText(mData.get(position).toString());
        holder.numberView.setText(mNumber.get(position).toString());
        holder.cb.setChecked(false);
        holder.cb.setTag(position);


        if(selected.indexOf(mNumber.get(position).toString()) >= 0)
        {

        holder.cb.setChecked(true);
        }

        return convertView;
    }

}

这里我在getView()上做的是取消选中所有的复选框,然后根据对应的文本视图手动再次选中那些需要选中的复选框。因此,如果用户在选中第一个复选框后向下滚动,视图中的所有复选框都将被取消选中,如果他再次向上滚动,那么所有的复选框都将被取消选中,但他之前单击的复选框将再次被选中。

iq0todco

iq0todco4#

我决定尝试使用setViewBinder方法。Сheckboxes的状态存储在SparseBooleanArray中。Сheckbox的状态随着您单击checkbox本身以及整个单元格而变化。
我的行:|文字检视|核取方块|

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
//        ..
    private SparseBooleanArray checkedItems = new SparseBooleanArray(); //for storing item state

    startManagingCursor(cursor);
    String[] from = new String[] { dbAdapter.COLUMN_NAME, dbAdapter.COLUMN_CHECK };
    int[] to = new int[] { R.id.item_name, R.id.item_check };
    recordsAdapter = new SimpleCursorAdapter(this, R.layout.items, cursor, from, to);

    recordsAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
            if (columnIndex == 2) { //2 - R.id.item_check
                    final CheckBox cb = (CheckBox) view; 
                    final int rowID = cursor.getInt(0); //cursor.getInt(0) - _id from table

                    if (checkedItems.indexOfKey(rowID) >= 0) {  //checkedItems contains rowID?
                        cb.setChecked(checkedItems.get(rowID));
                    } else if (cursor.getInt(2) > 0) {          //cursor.getInt(2): 0 - false, 1 - true
                        checkedItems.append(rowID, true);
                        cb.setChecked(true);
                    } else {
                        cb.setChecked(false);
                    }

                    cb.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (checkedItems.indexOfKey(rowID) >= 0) {
                                checkedItems.put(rowID, !(checkedItems.get(rowID)));
                            } else {
                                checkedItems.append(rowID, true);
                            }
                            cb.setChecked(checkedItems.get(rowID));
                            dbAdapter.updateItem(rowID, checkedItems.get(rowID)?1:0);
                        }
                    });
                    return true;
            }
            return false;
        }
    });

    itemsList.setAdapter(recordsAdapter);
    itemsList.setOnItemClickListener(this);
//      ..
}

//if click on TextView of row - CheckBox of row is set/unset
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
    TextView tv = (TextView) view.findViewById(R.id.item_name);
    ViewGroup row = (ViewGroup) tv.getParent();
    CheckBox cb = (CheckBox) row.getChildAt(1);
    cb.performClick();
}
0tdrvxhp

0tdrvxhp5#

我不明白,为什么不可能(像在HTML中那样)在XML中将ViewElement定义为数组。即:

<CheckBox
    android:id="@+id/myCheckBox[]"
    android:focusable="false"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true" />

并将一个值存储在int it [true| false]。这将使生活更容易,而不是使用复杂的源frickle。此外,数据(即当从横向切换到纵向)应该由android保存,而不会丢失。
也许在API 117中,版本toothscratch...

ie3xauqp

ie3xauqp6#

(sry,还不能评论)-关于Vikas Patidar的答案,这对我来说很有效-在使用异步加载(像使用Loader)时要注意,因为适配器的构造函数中的getCount将为零。
最后会出现索引错误(因为ArrayList永远不会被填充)。使用SparseBooleanArray而不是ArrayList,它也可以用于异步加载。

j5fpnvbx

j5fpnvbx7#

这里可能有点晚了,为了总结一下Vikas Patidar's的答案,这里是一个完整的实现,它使用了bindView方法,适用于那些使用CursorAdapter的人:

@Override
        public void bindView(View view, Context context, Cursor cursor) {

            final ViewHolder holder = (ViewHolder) view.getTag();
            final int position = cursor.getPosition();
            String name = (cursor.getString(cursor.getColumnIndexOrThrow("NotificationDateFor")));
            String image = cursor.getString(cursor.getColumnIndexOrThrow("imageUri"));

             System.out.println("cursor.getPosition(test): "+cursor.getPosition());

            holder.nametext.setText(name);
        //  setImage(image, holder.iv); 

            holder.chk.setOnClickListener(new OnClickListener(){

                @Override
                public void onClick(View v) {

                        if (holder.chk.isChecked()) {
                            itemChecked.set(position, true);
                           System.out.println("cursor.getPosition(true): "+position);
                        } else if (!holder.chk.isChecked()) {
                            itemChecked.set(position, false);
                            System.out.println("cursor.getPosition(false): "+position);
                            // AddDelete
                        }   
                }               
            });

            holder.chk.setChecked(itemChecked.get(cursor.getPosition()));

        }

注意:final int position = cursor.getPosition();有意义!

mkh04yzy

mkh04yzy8#

您可以通过使用Listview的内置多选模式来为自己节省很多麻烦。
(列表视图.选择模式_多个);

相关问题