Android 单击 listItem 检查错误的复选框 [英] Android Click on listItem checks wrong checkbox

查看:19
本文介绍了Android 单击 listItem 检查错误的复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过扩展 SimpleCursorAdapter 创建了一个自定义 ListView.结果是 IMAGE + CheckedTextView (Text + Checkbox).

I've created a custom ListView by extending SimpleCursorAdapter. The result is IMAGE + CheckedTextView (Text + Checkbox).

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

When I long click an Item, everything works fine - I get the right ID and details of the clicked Item.

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

The problem occurs when I try to mark an Item as checked but it checks the wrong checkbox.

例如:我的列表中有 9 个项目,按 1-9 排序.如果我单击 listItem 1,则会选中第 9 行的复选框.如果我点击第 4 项,第 6 行的复选框被选中,如果我点击中间的一行,它被选中.

For example: I have 9 items on my list, sorted 1-9. if I click on listItem 1, the checkbox on line 9 is being checked. if I click on item 4, the checkbox on line 6 is being checked and if I click on the middle line, it is being checked.

显然我在这里遗漏了一些东西:)请记住,当我长按该行(contextMenu 打开)时,一切正常.

Clearly I'm missing something here :) Do remember when I long click the line (contextMenu opens), everything works great.

这是听众:

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

            }
        });

感谢任何帮助!

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

Let me know If you need me to post more code.

谢谢!

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

btw, If I click on more than one... the PARTY continues... no obvious order...

适配器代码

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

推荐答案

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

Mayra is right - the problem has to do with the way the ListView is reusing your views. It's not as if there are 9 instances of the CheckedTextView object, one per view. Instead, there's a single one that is reused in all the rows. Thus you can't rely on the CheckedTextView object to hold the state of whether an item is checked. You'll need some additional data structure to hold whether a given row is checked For instance,

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

如果 ith<​​/code> 行应该被检查,则 ith<​​/code> 元素为真.然后在您的 itemClickListener 中:

Where the ith element is true iff the ith row should be checked. Then within your 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
        }
    });

然后在您的视图代码中:

Then within your view code:

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

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

This should solve your problem. An alternative approach would be to move the logic of whether the row is checked or not into the domain object that the row represents. That would be my preference.

这篇关于Android 单击 listItem 检查错误的复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆