运行如下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
相关产品推荐
相关产品推荐

