【问题标题】:CheckBox in ListView being reset when it leaves the screenListView 中的复选框在离开屏幕时被重置
【发布时间】:2014-11-14 01:24:01
【问题描述】:

我按照教程here 创建了一个自定义ListView,它显示带有类别标题的项目。我已经修改了list_item_entry.xml,在项目中添加了CheckBox

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:paddingRight="?android:attr/scrollbarSize" >

    <CheckBox
        android:id="@+id/option_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="6dp"
        android:focusable="false"
        android:clickable="false" />

    <TextView
        android:id="@+id/list_item_entry_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:gravity="center_vertical"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"
        android:ellipsize="marquee"
        android:fadingEdge="horizontal" />

</LinearLayout>

我的问题是,如果我检查了一些CheckBoxes,然后将它们从屏幕上滚动出来,当它们返回时,它们就没有被选中。但是listView.getCheckedItemPositions() 仍然显示该项目是checked

我很确定我的问题在于我的自定义 ArrayAdapter 中的 getView() 方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final Item i = items.get(position);
    if (i != null) {
        if(i.isSection()){
            SectionItem si = (SectionItem)i;
            convertView = vi.inflate(R.layout.list_item_section, parent, false);

            convertView.setOnClickListener(null);
            convertView.setOnLongClickListener(null);
            convertView.setLongClickable(false);

            final TextView sectionView =
                     (TextView) convertView.findViewById(R.id.list_item_section_text);
            sectionView.setText(si.getTitle());
        }else{
            EntryItem ei = (EntryItem)i;
            convertView = vi.inflate(R.layout. list_item_entry, parent, false);
            final TextView title =
                     (TextView) convertView.findViewById(R.id.list_item_entry_title);
            if (title != null) 
                title.setText(ei.getTitle());
        }
    }
    return convertView;
 }

我认为我在这里有两个问题,虽然我不知道如何解决:

  1. 每次使用 vi.inflate 都会导致 android 不断创建视图,这很糟糕(对此不确定)。我试图只在convertView == null 的情况下对其进行充气,但有时convertView 的格式会错误,即。 List_item_section 应该是 List_item_entry。每次都给它充气好吗?

  2. 我认为每次放大视图都会导致 CheckBoxes 被重置,尽管我可能对此有误。

那么我该如何做才能使复选框在离开并返回屏幕时保持选中状态?如果列表足够长,这个方法会用 Views 填充 Android 的内存吗?

更新: 我喜欢@user3815165 的答案,因为我不需要为没有复选框的sectionItem 存储checked 值。但正如我在评论中提到的,由于items 列表不在 Activity 的上下文中,因此当视图被销毁并产生错误时,是否检查每个 EntryItem 的值仍然存在。

所以我决定采用@Palash 的答案,即使它存储了不需要的数据(列表中每个SectionItem 仅有一个boolean 值)。效果很好。

【问题讨论】:

    标签: android android-listview android-arrayadapter android-checkbox


    【解决方案1】:

    您需要在您的活动中维护一个布尔类型的状态数组,将该数组传递给您的列表适配器,并在设置该位置的复选框检查状态时,您还需要在复选框的单击事件上更新该状态数组。 试试这个,你会得到想要的输出。

    //While Setting the checkbox in adapter
    
         if(bStatus[position]==false)
            {
                 itemSet.chSelectItem.setChecked(false);
            }else if(bStatus[position]==true)
                {
                  itemSet.chSelectItem.setChecked(true);
                }   
    

    在您的主要活动中

          //initilize Arraylist in main Activity
            boolean[] bStatus;
            bStatus = new boolean[BeanArray.size()];
            Arrays.fill(bStatus, false);
        MyAdapter adapter = new MyAdapter(this, BeanArray, bStatus);
    listView.setAdapter(adapter);
    

    【讨论】:

    • 所以在else 子句的末尾我会有checkBox.checked = savedState.get(position) 之类的东西?每次单击复选框时我都需要更新savedState[position]
    • 看上面的代码你会明白的,我的代码可以做你想做的事情。
    • 并且不要忘记在复选框的点击事件上更新状态数组
    • 你可以去掉if, else if,比如:itemSet.chSelect.setChecked(bStatus[position])
    • 也是我的getView 方法在浪费内存,还是它工作正常?
    【解决方案2】:
    class Item{
     boolean isSection;
     String title;
     boolean isOptionChecbox;
    
     //your getter/setter
    
        @Override
        public String toString() {
            return title;
        }
    }
    
    you Adapter:
    public class listAdapter extends ArrayAdapter<Item> {
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final Item i = items.get(position);
        if(i.isSection()){
                  convertView = vi.inflate(R.layout.list_item_section, parent, false);
                  convertView.setOnClickListener(null);
                  convertView.setOnLongClickListener(null);
                  convertView.setLongClickable(false);
                  final TextView sectionView = (TextView) convertView.findViewById(R.id.list_item_section_text);
                  sectionView.setText(si.getTitle());
           } else{
                  convertView = vi.inflate(R.layout. list_item_entry, parent, false);
                  final TextView title = (TextView) convertView.findViewById(R.id.list_item_entry_title);
                  if (title != null) title.setText(ei.getTitle());
    
                  CheckBox optionCheckbox = (CheckBox) convertView.findViewById(R.id.option_checkbox);
                  optionCheckbox.setChecked(ei.isOptionCheckbox());
                  optionCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                      @Override
                      public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                          item.setOptionCheckbox(b);
                      }
                });
           }      
        return convertView;
     }
    
    }
    

    【讨论】:

    • 这会产生一个错误。如果我离开活动并返回到它,我之前选中的复选框仍然被选中,但listView.getCheckedItemPositions() 表示没有选中。
    • 要解决这个问题,我必须在onCreate 中遍历items 并在每个人上调用setOptionCheckbox(false)
    • 据我所知,布尔值始终默认为 false。初始化为false不需要
    • 很确定所有值都需要初始化。但这不是问题。这是因为EntryItem 的列表是在应用程序首次启动时创建的,然后当我导航到此活动并选中一些框时,isOptionCheckbox() 被设置为 true。返回第一页并再次返回此活动,按原样重置所有复选框(因此ListView.getCheckedItemPositions() 不返回任何内容。但是将检查一些复选框,因为isOptionValue()EntryItems 是没有重置。
    • 好的。然后我也有疑问:1)为什么不使用单个对象而不是SectionItem 和EntryItem。 2)为什么您不能覆盖 onSaveInstanceState 并保留您的列表,以及当您重新启动此 Activity 以恢复您的列表时
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    相关资源
    最近更新 更多