Android点击listItem检查错误复选框

时间:2010-10-24 21:46:24

标签: android listview checkedtextview

我通过扩展SimpleCursorAdapter创建了一个自定义ListView。 结果是IMAGE + CheckedTextView(文本+复选框)。

当我长按一个项目时,一切正常 - 我得到了正确的ID和点击项目的详细信息。

当我尝试将项目标记为已选中但检查错误的复选框时,会出现问题。

例如:我的列表中有9个项目,排序为1-9。如果我点击listItem 1,则检查第9行的复选框。如果我点击第4项,则会检查第6行的复选框,如果我点击中间的行,则会进行检查。

显然我在这里遗漏了一些东西:) 请记住,当我长按行(contextMenu打开)时,一切都很好。

这是听众:

lv.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle);

                if (!markedItem.isChecked()) {
                    markedItem.setChecked(true);
                } else {
                    markedItem.setChecked(false);
                }

            }
        });

感谢任何帮助!

如果您需要我发布更多代码,请告诉我。

谢谢!

顺便说一句,如果我点击多个...... PARTY继续......没有明显的顺序...

编辑:适配器代码

public class ImageCursorAdapter extends SimpleCursorAdapter {

    private Cursor c;
    private Context context;

    private String url;
    private TextView bUrl;

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

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

        this.c.moveToPosition(pos);

        final TextView bTitle = (TextView) v.findViewById(R.id.btitle);
        String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE));


        byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON));

        if (favicon != null) {
            ImageView iv = (ImageView) v.findViewById(R.id.bimage);
            iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length));
        }
        bTitle.setText(bookmark);

        return (v);
    }
}

1 个答案:

答案 0 :(得分:11)

Mayra是对的 - 问题与ListView重用视图的方式有关。它不像CheckedTextView个对象的9个实例,每个视图一个。相反,只有一个在所有行中重用。因此,您不能依赖CheckedTextView对象来保持项目是否被选中的状态。您需要一些额外的数据结构来保存是否检查了给定的行。例如,

ArrayList<Boolean> checkedStates = new ArrayList<Boolean>();

如果ith行应该被检查,ith元素为真。然后在你的itemClickListener中:

lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            boolean currentlyChecked = checkedStates.get(position);
            checkedStates.set(position, !currentlyChecked);
            // Refresh the list
        }
    });

然后在您的视图代码中:

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

    this.c.moveToPosition(pos);

    final TextView bTitle = (TextView) v.findViewById(R.id.btitle);
    String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE));


    byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON));

    if (favicon != null) {
        ImageView iv = (ImageView) v.findViewById(R.id.bimage);
        iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length));
    }
    bTitle.setText(bookmark);


    // Change the state of the checkbox to match that of the row's checked state.
    // This check box item is reused for every row, so we need to reset its state each
    // time the row is rendered.
    CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle);
    markedItem.setChecked(checkedStates.get(pos));


    return (v);
}

这应该可以解决您的问题。另一种方法是将行是否被检查的逻辑移动到行所代表的域对象中。这是我的偏好。