8

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

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

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

例如:我的清单上有 9 个项目,按 1-9 排序。如果我单击 listItem 1,则会检查第 9 行的复选框。如果我点击第 4 项,第 6 行的复选框被选中,如果我点击中间行,它被选中。

显然我在这里遗漏了一些东西:) 请记住,当我长按该行(上下文菜单打开)时,一切正常。

这是听众:

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

1 回答 1

11

Mayra 是对的 - 问题与 ListView 重用您的视图的方式有关。并不是说对象有 9 个实例CheckedTextView,每个视图一个。相反,有一个在所有行中重复使用。因此,您不能依赖 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);
}

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

于 2010-10-24T23:49:55.087 回答