简体   繁体   English

Android 如何知道选中了哪个复选框

[英]Android How to know which check box is selected

I'm making my first Android application and I'm having a problem for which I can't find the answer anywhere on Google.我正在制作我的第一个 Android 应用程序,但我遇到了一个问题,我在谷歌的任何地方都找不到答案。

I want a list of items with checkboxes.我想要一个带有复选框的项目列表。 I want both the item itself and the checkbox to be clickable.我希望项目本身和复选框都是可点击的。

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

Don't worry about the chosen variable.不要担心选择的变量。 I wrote that to simply the code.我把它写成简单的代码。 It actually corresponds to a value in a database.它实际上对应于数据库中的一个值。 The clicking on an item works just fine.单击一个项目就可以了。 However when I click on a checkbox what happens is this:但是,当我单击复选框时,会发生以下情况:

  • the checkbox in which I clicked appears selected (this is the work of the Android's UI)我点击的复选框显示为选中(这是Android UI的工作)
  • the checkbox that internally is checked is the last one on the screen whichever it is, ie, if I my screen displays 8 items and I click in one of them (doesn't matter which one) the check appears in the correct checkbox but internally, the 8th item is the one getting checked.内部选中的复选框是屏幕上的最后一个复选框,无论它是什么,即,如果我的屏幕显示 8 个项目并且我单击其中一个项目(不管是哪个项目),则检查出现在正确的复选框中,但在内部,第 8 项是要检查的项。

I would appreciate any help you could provide me.我将不胜感激您能为我提供的任何帮助。 Thanks in advance.提前致谢。

Actually, the implementation backing chosen is key.实际上, chosen的实施支持是关键。 Android does some optimization with list views to allow you to reuse the list item views to avoid excessive object creation and garbage collection (which would often lead to jerky scrolling). Android 对列表视图进行了一些优化,以允许您重用列表项视图以避免过多的 object 创建和垃圾收集(这通常会导致滚动不顺畅)。 As such, you have to make sure that whenever relevant, you know exactly which list item you're working with.因此,您必须确保无论何时相关,您都确切知道您正在使用哪个列表项。

Let's say that you have a 100 list items.假设您有 100 个列表项。 Your screen is probably not going to be able to display all of them.您的屏幕可能无法显示所有这些。 You might only show ten items at a time.您一次只能显示十个项目。 So 10 views (really view hierarchies) are created to display those visible items.因此创建了 10 个视图(真正的视图层次结构)来显示这些可见项目。 When you scroll down to the next ten items, instead of creating 10 new views (for a total of 20), the list might only create one more (to cover the case where half of one item is showing at the top and half of one is showing at the bottom of the screen for a total of 11 items visible on the screen) and the rest of items reuse the views created before.当您向下滚动到接下来的 10 个项目时,而不是创建 10 个新视图(总共 20 个),列表可能只会再创建一个(以涵盖一个项目的一半显示在顶部和一个项目的一半的情况显示在屏幕底部,总共有 11 个项目在屏幕上可见)并且项目的 rest 重用了之前创建的视图。

So a conceptual table representing the first screen might look like this:因此,代表第一个屏幕的概念表可能如下所示:

Item     View
-------  --------
Item 1   View 1
Item 2   View 2
Item 3   View 3
Item 4   View 4
Item 5   View 5
Item 6   View 6
Item 7   View 7
Item 8   View 8
Item 9   View 9
Item 10  View 10

And for after scrolling down ten items, it might look a little like this (probably not exactly, but this gets you the idea):向下滚动十个项目后,它可能看起来有点像这样(可能不完全是,但这让你明白了):

Item     View
-------  --------
Item 11  View 1
Item 12  View 2
Item 13  View 3
Item 14  View 4
Item 15  View 5
Item 16  View 6
Item 17  View 7
Item 18  View 8
Item 19  View 9
Item 20  View 10

So what you can gather from this is that a single given view can represent different items as you scroll around.因此,您可以从中收集到的是,单个给定视图可以在您滚动时表示不同的项目。 This means that your event handlers have to be a little more dynamic in how they find the item they're related to.这意味着您的事件处理程序必须更加动态地查找与其相关的项目。

All this is to give you a bit of background so that you can change how you're implementing your getView method.所有这些都是为了给您一些背景知识,以便您可以更改实现getView方法的方式。 Here's your actual problem: the variable item is in the scope of your Adapter .这是您的实际问题:变量item位于Adapter的 scope 中。 Unfortunately, I'm guessing that your code that you haven't posted here that you've replaced with chosen uses item .不幸的是,我猜您没有在此处发布的代码已替换为chosen uses item You set item whenever an item view gets created.每当创建项目视图时,您就设置item This means that after those first 8 views are created, item is set to the 8th item in your list.这意味着在创建前 8 个视图之后, item将设置为列表中的第 8 个项目。 Whenever you click on a checkbox, you're using item which is the 8th item and not the item that corresponds to the list item view that you clicked.每当您单击复选框时,您使用的是第 8 个item ,而不是与您单击的列表项视图相对应的项目。

Here's the structure for getView that I'd recommend:这是我推荐的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;
    }
}

Note that I've gotten rid of the class-level item variable.请注意,我已经摆脱了类级别的item变量。

Try this尝试这个

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

You should save isChecked value in your MyItem object and explicit set checked to checkbox in getView method of your adapter.您应该将 isChecked 值保存在 MyItem object 中,并在适配器的 getView 方法中将选中的复选框显式设置为复选框。 Use onCheckedChangedListener.使用 onCheckedChangedListener。

If I am following your explanation it sounds like you have a list and each row in the list has a Checkbox and a TextView.如果我按照你的解释,听起来你有一个列表,列表中的每一行都有一个复选框和一个 TextView。 In my app I have something similar and instead of trying to make both the Checkbox and TextView clickable and react to that I use the ListView's onItemclick.在我的应用程序中,我有类似的东西,而不是尝试使 Checkbox 和 TextView 都可点击并对此做出反应,我使用 ListView 的 onItemclick。 When you catch the user pressed an item in the list, then in the code you can check or un-check the Checkbox.当您捕捉到用户按下列表中的某个项目时,您可以在代码中选中或取消选中复选框。 It gives the visual impression that the user is able to check the box, but is super easy to implement.它给人的视觉印象是用户可以选中该框,但非常容易实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM