【问题标题】:Android How to know which check box is selectedAndroid 如何知道选中了哪个复选框
【发布时间】:2011-10-27 11:46:01
【问题描述】:

我正在制作我的第一个 Android 应用程序,但我遇到了一个在 Google 上找不到任何答案的问题。

我想要一个带有复选框的项目列表。我希望项目本身和复选框都是可点击的。

    public class MyItem extends ListActivity {
        private ArrayList<MyItem> items;
        public void onCreate(Bundle savedInstanceState) {
            /* code which creates instances of MyItem and inserts them on the *list* variable */
        MyArrayAdapter adapter = new MyArrayAdapter(this, R.layout.my_item, list);

        setListAdapater(adapter);
        setContentView(R.layout.items_list);
    }
        public onListItemClick(ListView l, View v, int position, long id){
            //handles the click on an item
        }

    public class MyArrayAdapter extends ArrayAdapter<MyItem>{
        private MyItem item;
        public MyArrayAdapter(Context context, int resourceId, ArrayList<MyItem> list){
            //code for the constructor
        }
        public getView(int position, View convertView, ViewGroup parent){
            convertView = inflater.inflate(resourceId, null);


            this.item = list.get(position);
            if (this.item == null) {
                return convertView;
            }
            else{
                if (resourceId == R.layout.my_item) {
                    final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox);

                    if(cb != null){
                        //initially
                        if(chosen)
                            cb.setChecked(true);
                        else
                            cb.setChecked(false);
                        //set listener
                        cb.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View arg0) {
                                if(cb.isChecked())
                                    chosen = true;
                                else
                                    chosen = false;
                            }
                        });
                    }
                }
            return convertView;
        }
    }    
}

不要担心选择的变量。我把它写成简单的代码。它实际上对应于数据库中的一个值。单击一个项目就可以了。但是,当我单击复选框时,会发生这种情况:

  • 我单击的复选框显示为选中状态(这是 Android 用户界面的工作)
  • 内部选中的复选框是屏幕上的最后一个复选框,无论它是什么,即,如果我的屏幕显示 8 个项目并且我单击其中一个(不管是哪一个),则检查显示在正确的复选框,但在内部,第 8 项是被选中的项。

如果您能为我提供任何帮助,我将不胜感激。提前致谢。

【问题讨论】:

    标签: android list checkbox listactivity android-arrayadapter


    【解决方案1】:

    实际上,支持chosen 的实现是关键。 Android 对列表视图进行了一些优化,以允许您重用列表项视图以避免过多的对象创建和垃圾收集(这通常会导致滚动不顺畅)。因此,您必须确保无论何时相关,您都确切知道您正在使用哪个列表项。

    假设您有 100 个列表项。您的屏幕可能无法显示所有这些。您一次只能显示十个项目。因此创建了 10 个视图(真正的视图层次结构)来显示这些可见项目。当您向下滚动到接下来的 10 个项目时,而不是创建 10 个新视图(总共 20 个),列表可能只会再创建一个(以涵盖一个项目的一半显示在顶部和一个项目的一半的情况显示在屏幕底部,总共有 11 个项目在屏幕上可见),其余项目重用之前创建的视图。

    因此,代表第一个屏幕的概念表可能如下所示:

    项目视图 -------- -------- 项目 1 查看 1 项目 2 查看 2 项目 3 查看 3 项目 4 查看 4 项目 5 查看 5 项目 6 查看 6 项目 7 查看 7 项目 8 查看 8 项目 9 查看 9 项目 10 查看 10

    向下滚动十个项目后,它可能看起来有点像这样(可能不完全是,但这让你明白了):

    项目视图 -------- -------- 项目 11 查看 1 项目 12 查看 2 项目 13 查看 3 项目 14 查看 4 项目 15 查看 5 项目 16 查看 6 项目 17 查看 7 项目 18 查看 8 项目 19 查看 9 项目 20 查看 10

    因此,您可以从中收集到的是,当您滚动时,单个给定视图可以表示不同的项目。这意味着您的事件处理程序必须更加动态地查找与其相关的项目。

    所有这些都是为了给您一些背景知识,以便您可以更改实现 getView 方法的方式。这是您的实际问题:变量item 在您的Adapter 范围内。不幸的是,我猜您没有在此处发布但已替换为chosen 的代码使用item。每当创建项目视图时,您就设置item。这意味着在创建前 8 个视图之后,item 被设置为列表中的第 8 项。每当您单击复选框时,您都在使用item,它是第 8 项,而不是与您单击的列表项视图对应的项。

    这是我推荐的getView 的结构:

    public getView(int position, View convertView, ViewGroup parent){
            View view = convertView;
            if (view == null) {
                view = inflater.inflate(R.layout.my_item, null);
            }
    
            final MyItem item = list.get(position);
            final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox);
            // This stores a reference to the actual item in the checkbox
            cb.setTag(item);
    
            if(item.chosen)
                cb.setChecked(true);
            else
                cb.setChecked(false);
    
            //set listener
            cb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // This gets the correct item to work with.
                    final MyItem clickedItem = (MyItem) view.getTag();
                    if(cb.isChecked())
                        clickedItem.chosen = true;
                    else
                        clickedItem.chosen = false;
                }
            });
    
            return view;
        }
    }
    

    请注意,我已经删除了类级别的 item 变量。

    【讨论】:

    • 除了一个细节之外,它就像一种魅力。 setTag/getTag 必须不是针对视图而是针对复选框。谢谢,非常感谢:D
    • 已更新以修复您指出的错误,以防万一其他人遇到此代码。
    【解决方案2】:

    试试这个

    public getView(int position, View convertView, ViewGroup parent){
        View view = convertView;
        if (view == null) {
            view = inflater.inflate(R.layout.my_item, null);
        }
    
        final MyItem item = list.get(position);
        // This stores a reference to the actual item in the view
        view.setTag(item);
    
        final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox);
    
        //set listener
        cb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // This gets the correct item to work with.
                final MyItem clickedItem = (MyItem) view.getTag();
                if(cb.isChecked())
                    clickedItem.chosen = true;
                else
                    clickedItem.chosen = false;
            }
        });
    
    
        cb.setChecked(item.chosen);
        return view;
    }
    

    【讨论】:

    • 为什么不 clickedItem.chosen = cb.isChecked()?
    【解决方案3】:

    您应该将 isChecked 值保存在 MyItem 对象中,并在适配器的 getView 方法中将选中的复选框显式设置为复选框。使用 onCheckedChangedListener。

    【讨论】:

    • 我这样做。我正在使用 OnClickListener,因为我正在尝试使用 OnCheckedChangeListener 但它不起作用,所以我尝试了 onClick。结果是一样的。我的问题不是保存更改(它将更改保存到列表中的第 8 项)。我的问题是,当我实际点击 1 号或其他任何内容时,它说我点击的是 8 号。
    【解决方案4】:

    如果我按照你的解释,听起来你有一个列表,列表中的每一行都有一个复选框和一个 TextView。在我的应用程序中,我有类似的东西,而不是尝试使 Checkbox 和 TextView 都可点击并对此做出反应,我使用 ListView 的 onItemclick。当您捕捉到用户按下列表中的某个项目时,您可以在代码中选中或取消选中复选框。它给人的视觉印象是用户可以选中该框,但非常容易实现。

    【讨论】:

    • 我不太明白你的回答,但@kabuko 的回答解决了这个问题。无论如何谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    相关资源
    最近更新 更多