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

时间:2011-08-15 18:24:24

标签: android list checkbox listactivity android-arrayadapter

我正在制作我的第一个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 UI的工作)
  • 内部检查的复选框是屏幕上的最后一个,无论它是什么,即,如果我的屏幕显示8个项目,我点击其中一个(无关紧要哪一个)检查显示在正确的复选框,但在内部,第8项是获得检查的项目。

感谢您提供给我的任何帮助。提前谢谢。

4 个答案:

答案 0 :(得分:6)

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

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

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

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

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

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

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

所有这些都是为了给您一些背景信息,以便您可以更改实施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变量。

答案 1 :(得分: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;
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果我按照你的说明理解你有一个列表,列表中的每一行都有一个Checkbox和一个TextView。在我的应用程序中,我有类似的东西,而不是试图使Checkbox和TextView可单击并对其做出反应,我使用ListView的onItemclick。当您抓住用户按下列表中的项目时,您可以在代码中选中或取消选中复选框。它给人的视觉印象是用户可以选中复选框,但非常容易实现。