列表中的复选框被意外选中

发布于 2024-08-21 20:18:39 字数 3174 浏览 2 评论 0原文

我在自定义 simpleCursorAdapter 绑定的列表中有复选框列表。 在我的自定义 simpleCursorAdapter 中,我用我的修改覆盖了 newViewbindView。 我设法以某种方式进行多项选择。 奇怪的是,在我从列表中删除任何项目后,第一个项目的复选框突然被选中。这是怎么发生的?我该如何解决?

我的 SimpleCursorAdapter 类:

public class MyListCursorAdapter extends SimpleCursorAdapter
{
    private Context context;
    private int layout;

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

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent)
    {
        Cursor c = getCursor();
        final LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(layout, parent, false);
        CheckBox chkBoxBtn = (CheckBox) v.findViewById (R.id.deleteTwittChkBox);
        if (chkBoxBtn != null)
        {
            chkBoxBtn.setChecked(false);
        }
        return v;
    }

    @Override
    public void bindView(View v, Context context, Cursor c)
    {
        --binding view to my textsview in my items
        //now it's the importat part:
            CheckBox chkBoxBtn = (CheckBox) v.findViewById(R.id.deleteTwittChkBox);
    if (chkBoxBtn != null)
    {
        chkBoxBtn.setId(Integer.valueOf(c.getString(c
                .getColumnIndex(MyUsers.User._ID))));
        chkBoxBtn.setOnClickListener(new OnItemClickListener(chkBoxBtn, v));
        chkBoxBtn.setChecked(false);
    }
    }

    //i couldnt find another way of doing this, but this is how i set listeners to my checkboxses
    static ArrayList<String> checkedItemsList = new ArrayList<String>();

    private class OnItemClickListener implements OnClickListener
    {
        private int mPosition;
        private CheckBox chkBox;
        OnItemClickListener(CheckBox mChkBox, View v)
        {
            chkBox = mChkBox;
            chkBox.setChecked(false);
        }

        @Override
        public void onClick(View v)
        {
            if (chkBox.isChecked())
            {
                checkedItemsList.add(String.valueOf(chkBox.getId()));
            }
            else
            {
                checkedItemsList.remove(String.valueOf(chkBox.getId()));
            }
        }
    }
}

以下是 ListActivity 类中的代码部分,它描述了删除选中框项目的按钮:

OnClickListener btListener = new OnClickListener()
{
    public void onClick(View view)
    {
        // long[] items = listView.getCheckItemIds();
        int x = 0;
        Uri myUri = Uri
        .parse("content://com.idan.datastorageprovider/users");
        String where = "_id" + "=?";
        //here i am tatking all checkboxes which ive added from the  adapter class
        ArrayList<String> checkedItemsList =   MySimpleCursorAdapter.checkedItemsList;
        for (String itemID : checkedItemsList)
        {
            getContentResolver()
            .delete(myUri, where, new String[] { itemID});
            checkedItemsList.remove(itemID);
        }
    }
};

I have list of checkboxes in list binded by Custom simpleCursorAdapter.
In my custom simpleCursorAdapter, I've overridden newView and bindView with my modifications.
I've managed somehow to do multichoice.
The wierd thing is, after I delete any item from my list, the first item's checkbox is being checked all of a sudden. How does that happen? How can I solve it?

My SimpleCursorAdapter class:

public class MyListCursorAdapter extends SimpleCursorAdapter
{
    private Context context;
    private int layout;

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

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent)
    {
        Cursor c = getCursor();
        final LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(layout, parent, false);
        CheckBox chkBoxBtn = (CheckBox) v.findViewById (R.id.deleteTwittChkBox);
        if (chkBoxBtn != null)
        {
            chkBoxBtn.setChecked(false);
        }
        return v;
    }

    @Override
    public void bindView(View v, Context context, Cursor c)
    {
        --binding view to my textsview in my items
        //now it's the importat part:
            CheckBox chkBoxBtn = (CheckBox) v.findViewById(R.id.deleteTwittChkBox);
    if (chkBoxBtn != null)
    {
        chkBoxBtn.setId(Integer.valueOf(c.getString(c
                .getColumnIndex(MyUsers.User._ID))));
        chkBoxBtn.setOnClickListener(new OnItemClickListener(chkBoxBtn, v));
        chkBoxBtn.setChecked(false);
    }
    }

    //i couldnt find another way of doing this, but this is how i set listeners to my checkboxses
    static ArrayList<String> checkedItemsList = new ArrayList<String>();

    private class OnItemClickListener implements OnClickListener
    {
        private int mPosition;
        private CheckBox chkBox;
        OnItemClickListener(CheckBox mChkBox, View v)
        {
            chkBox = mChkBox;
            chkBox.setChecked(false);
        }

        @Override
        public void onClick(View v)
        {
            if (chkBox.isChecked())
            {
                checkedItemsList.add(String.valueOf(chkBox.getId()));
            }
            else
            {
                checkedItemsList.remove(String.valueOf(chkBox.getId()));
            }
        }
    }
}

Here is the code part from the ListActivity class which describes the button that deletes the checked box items:

OnClickListener btListener = new OnClickListener()
{
    public void onClick(View view)
    {
        // long[] items = listView.getCheckItemIds();
        int x = 0;
        Uri myUri = Uri
        .parse("content://com.idan.datastorageprovider/users");
        String where = "_id" + "=?";
        //here i am tatking all checkboxes which ive added from the  adapter class
        ArrayList<String> checkedItemsList =   MySimpleCursorAdapter.checkedItemsList;
        for (String itemID : checkedItemsList)
        {
            getContentResolver()
            .delete(myUri, where, new String[] { itemID});
            checkedItemsList.remove(itemID);
        }
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

惜醉颜 2024-08-28 20:18:39

我怀疑 SimpleCursorAdapter 是在这里扩展的正确类。

“已检查”状态是否以任何方式连接到数据 XML?不?所以您需要自己的定制适配器!

基本上所有适配器都必须实现一种从给定元素(更准确地说是元素位置!)生成视图的方法。这将在列表想要显示元素的任何时候被调用。现在,它使用的技巧是重新使用以前创建的不再在屏幕上看到的列表视图元素!因此:当您向下滚动列表并且元素在顶部消失时,该视图对象将被重新用于下一个出现的项目。

因此,当使用应该重用的给定“旧”视图调用此方法时,必须根据元素数据设置所有包含的元素。如果复选框是该游戏的一部分,您将必须拥有一个存储选中状态的存储空间!仅有一个复选框是不够的,因为有列表元素,复选框对象就会更少!

SimpleCursorAdapters 的作用是——是的——代表简单的东西。描述数据的 XML(图像和文本,如文档所述)。由于这种简单性,您在这里要做的就是提供一种创建新元素视图对象的方法 - 您根本不会拦截重用过程!它基本上只知道如何将数据放入现有的视图对象中 - 但它缺乏如何处理选中/未选中框的知识!

您的解决方案:编写您自己的 BaseAdapter 扩展并执行必须执行的操作:实现“getView”(以及其他一些方法,如 getItem、getItemId 和 getCount)。一点也不难!
API 演示 使用 BaseAdapter 并且此处的 mExpanded 状态与您的复选框状态基本相同!

祝你好运!

I doubt that SimpleCursorAdapter is the right class to extend here.

Is the "checked" state connected to the data XML in any way? No? So you need your own custom adapter!

Basically all adapters have to implement a way to generate a view from a given element (more precisely an element position!). This will be called at any time where the list wants to display an element. Now, the trick it uses is to re-use formerly created list view elements that cannot be seen on screen any more! Thus: when you scroll your list down and an element disappears at the top, EXACTLY this view object will be re-used for the next appearing item.

So, when this method is called with a given "old" view that should be re-used, all contained elements will have to be set according the elements data. If a checkbox is part of this game, you will have to have a storage for the checked state! It is not sufficient to have a checkbox as there will be less checkbox objects as there are list elements!

SimpleCursorAdapters are there to - yeah - represent SIMPLE things. An XML describing data (images and text, as the documentation states). Because of this simplicity all you have to do here is provide a method to create NEW element view objects - you are not intercepting the re-use process AT ALL! It basically only knows how to put the data into an existing view object - but it is lacking the knowledge of how to handle checked/unchecked boxes!

Your solution: write your own BaseAdapter extension and do what has to be done: implement "getView" (and some other methods like getItem, getItemId and getCount). It's not hard at all!
This API Demo uses a BaseAdapter and the mExpanded state here is basically identical to your checkbox states!

Good luck!

萌酱 2024-08-28 20:18:39

当您修改数据。

You might need to call notifyDataSetChanged when you modify the data.

终止放荡 2024-08-28 20:18:39

问题可能是您从 onItemClickListener 中调用 setChecked。解决此问题的一种巧妙方法是在侦听器中调用 setChecked 之前和之后执行以下操作:

chkBox.setClickable(false);
chkBox.setChecked(false);
checkBox.setClickable(true);

这将防止您在手动调用 setChecked 时调用 onItemClickListener。

The problem is probably that you're calling setChecked from within the onItemClickListener. One hacky way around this is to do the following before and after you call setChecked from within your listener:

chkBox.setClickable(false);
chkBox.setChecked(false);
checkBox.setClickable(true);

This will prevent your onItemClickListener from getting called when you manually call setChecked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文