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

运行如下Flutter代码时滚动屏幕复选框自动取消选中该如何解决

问题原因

你的复选框选中状态存储在LevelCard的私有State中,当列表滚动到LevelCard离开可见区域时,Flutter会自动销毁回收该组件实例,等滚动回对应位置时组件会重新初始化,内部的_checkValue会重置为默认的false,就会出现选中状态丢失的情况。

解决方法
  • 状态上移:将所有卡片的选中状态统一放到列表的父级组件中维护,不要存在子卡片内部
  • 子组件改为无状态组件,通过参数接收选中状态、传递选中变更事件

修改后的LevelCard代码

import 'package:flutter/material.dart';
import 'package:glassmorphism/glassmorphism.dart';

// 改为无状态组件,状态由父级维护
class LevelCard extends StatelessWidget {
  final int index;
  final bool isChecked;
  final ValueChanged<bool> onChecked;

  const LevelCard({
    super.key,
    required this.index,
    required this.isChecked,
    required this.onChecked,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        // 点击时触发回调,把新的状态传给父级
        onChecked(true);
      },
      child: GlassmorphicContainer(
          margin: const EdgeInsets.all(5),
          width: 350,
          height: 350,
          borderRadius: 20,
          blur: 20,
          alignment: Alignment.bottomCenter,
          border: 2,
          linearGradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [
                const Color(0xFFffffff).withOpacity(0.1),
                const Color(0xFFFFFFFF).withOpacity(0.05),
              ],
              stops: const [
                0.1,
                1,
              ]),
          borderGradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              const Color(0xFFffffff).withOpacity(0.5),
              const Color(0xFFFFFFFF).withOpacity(0.5),
            ],
          ),
          child: Container(
            height: double.maxFinite,
            child: Column(
              children: [
                Container(
                  child: Checkbox(
                    shape: const CircleBorder(),
                    activeColor: Colors.green[300],
                    // 接收父级传的选中状态
                    value: isChecked,
                    onChanged: (_) {},
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    (index + 1).toString(),
                    style: const TextStyle(
                      fontWeight: FontWeight.bold,
                      color: Colors.black87,
                      fontSize: 15,
                    ),
                  ),
                ),
                const Text(
                  'Play',
                  style: TextStyle(color: Colors.black87),
                )
              ],
            ),
          )),
    );
  }
}

父组件使用示例

class LevelListPage extends StatefulWidget {
  const LevelListPage({super.key});

  @override
  State<LevelListPage> createState() => _LevelListPageState();
}

class _LevelListPageState extends State<LevelListPage> {
  // 父级统一维护所有卡片的选中状态,假设有20个关卡
  final List<bool> _checkedStatus = List.generate(20, (index) => false);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 20,
        itemBuilder: (context, index) {
          return LevelCard(
            index: index,
            isChecked: _checkedStatus[index],
            onChecked: (newValue) {
              setState(() {
                _checkedStatus[index] = newValue;
              });
            },
          );
        },
      ),
    );
  }
}
可选优化

如果希望列表项不被回收,可以给每个LevelCard设置唯一的Key,或者将列表的addAutomaticKeepAlives属性设为true,但更推荐的还是状态上移的方案,符合Flutter的状态管理规范。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:27:02