You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android如何保存ListView CHOICE_MODE_MULTIPLE的复选框勾选状态?

嘿,我来帮你搞定ListView多选状态保存的问题~先看你代码里的几个小问题:你自定义了FM1Adapter但没用到,反而用了ArrayAdapter;还有mListView.setItemChecked()没传参数会报错;另外getCheckedItemPositions()调用时机不对,得在要保存状态的时候用才行。

下面分两种情况给你解决方案:


方法一:用系统自带的多选布局(最简单)

你代码里提到了android.R.layout.simple_list_item_multiple_choice,这个布局自带CheckBox,而且ListView的CHOICE_MODE_MULTIPLE会帮我们管理选中状态,不用自己处理CheckBox逻辑。

步骤1:保存选中状态

在Fragment的onSaveInstanceState方法里保存选中的位置,这样横竖屏切换或者Fragment重建时能恢复:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // 获取所有选中项的状态
    SparseBooleanArray checkedPositions = mListView.getCheckedItemPositions();
    ArrayList<Integer> selectedItems = new ArrayList<>();
    // 把选中的位置转成ArrayList(Bundle能直接存这个类型)
    for (int i = 0; i < checkedPositions.size(); i++) {
        int position = checkedPositions.keyAt(i);
        if (checkedPositions.valueAt(i)) {
            selectedItems.add(position);
        }
    }
    outState.putIntegerArrayList("selected_check_items", selectedItems);
}

步骤2:恢复选中状态

在你设置好Adapter之后,读取之前保存的状态,逐个设置item为选中:

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { 
    View rootView = inflater.inflate(R.layout.fragment_check_tab1,container,false); 
    mListView = rootView.findViewById(R.id.check_ListView1); 
    mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 

    // 初始化Adapter
    ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(),
            android.R.layout.simple_list_item_multiple_choice, air_list); 
    mListView.setAdapter(adapter); 

    // 恢复选中状态
    if (savedInstanceState != null) {
        ArrayList<Integer> selectedItems = savedInstanceState.getIntegerArrayList("selected_check_items");
        if (selectedItems != null) {
            for (int position : selectedItems) {
                // 注意position不能超出列表长度
                if (position < air_list.length) {
                    mListView.setItemChecked(position, true);
                }
            }
        }
    }

    return rootView; 
}

方法二:自定义Adapter(如果需要自定义布局)

如果你一定要用自己的布局(比如你代码里的FM1Adapter),得自己管理选中状态,同时和ListView的状态同步,避免冲突。

步骤1:自定义item布局

先写一个包含TextView和CheckBox的布局item_check.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:padding="16dp">

    <CheckBox
        android:id="@+id/item_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:textColor="@android:color/black"
        android:layout_marginStart="16dp"/>
</LinearLayout>

步骤2:修改自定义Adapter

让Adapter自己维护选中状态,同时和ListView联动:

class FM1Adapter extends BaseAdapter{
    private SparseBooleanArray mCheckedStates;
    private ListView mListView;

    // 构造函数:传入之前保存的选中状态和ListView实例
    public FM1Adapter(SparseBooleanArray savedStates, ListView listView) {
        mCheckedStates = savedStates != null ? savedStates : new SparseBooleanArray();
        mListView = listView;
    }

    @Override
    public int getCount() {
        return air_list.length;
    }

    @Override
    public Object getItem(int position) {
        return air_list[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_check, parent, false);
            holder = new ViewHolder();
            holder.textView = convertView.findViewById(R.id.item_text);
            holder.checkBox = convertView.findViewById(R.id.item_checkbox);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.textView.setText(air_list[position]);
        // 设置CheckBox的选中状态
        holder.checkBox.setChecked(mCheckedStates.get(position, false));

        // 监听CheckBox点击,更新状态并同步到ListView
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mCheckedStates.put(position, isChecked);
                mListView.setItemChecked(position, isChecked);
            }
        });

        return convertView;
    }

    // 提供方法获取当前选中状态,方便保存
    public SparseBooleanArray getCheckedStates() {
        return mCheckedStates;
    }

    // ViewHolder优化性能
    static class ViewHolder {
        TextView textView;
        CheckBox checkBox;
    }
}

步骤3:保存和恢复状态

在Fragment里保存和恢复:

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { 
    View rootView = inflater.inflate(R.layout.fragment_check_tab1,container,false); 
    mListView = rootView.findViewById(R.id.check_ListView1); 
    mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 

    // 读取保存的状态
    SparseBooleanArray savedStates = null;
    if (savedInstanceState != null) {
        // 把Bundle里的ArrayList转成SparseBooleanArray
        ArrayList<Integer> selectedItems = savedInstanceState.getIntegerArrayList("selected_check_items");
        if (selectedItems != null) {
            savedStates = new SparseBooleanArray();
            for (int position : selectedItems) {
                savedStates.put(position, true);
            }
        }
    }

    // 初始化自定义Adapter
    FM1Adapter adapter = new FM1Adapter(savedStates, mListView);
    mListView.setAdapter(adapter); 

    return rootView; 
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // 获取Adapter里的选中状态
    FM1Adapter adapter = (FM1Adapter) mListView.getAdapter();
    SparseBooleanArray checkedStates = adapter.getCheckedStates();
    ArrayList<Integer> selectedItems = new ArrayList<>();
    for (int i = 0; i < checkedStates.size(); i++) {
        int position = checkedStates.keyAt(i);
        if (checkedStates.valueAt(i)) {
            selectedItems.add(position);
        }
    }
    outState.putIntegerArrayList("selected_check_items", selectedItems);
}

小提醒:如果你想长期保存(比如退出APP再打开也能恢复),可以把选中状态存到SharedPreferences里,原理和存Bundle一样,只是把ArrayList转成字符串存储,读取时再转回来就行。

内容的提问来源于stack exchange,提问作者Hyojun Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:34:41