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

Flutter移除列表项后ExpansionTile触发类型转换错误

问题:移除ListView列表项后出现类型转换错误

移除列表项后抛出以下错误:

The following _CastError was thrown building SingleChildScrollView(dependencies:
[PrimaryScrollController]):
type 'bool' is not a subtype of type 'double?' in type cast

The relevant error-causing widget was: 
When the exception was thrown, this was the stack: 
#0      ScrollPosition.restoreScrollOffset (package:flutter/src/widgets/scroll_position.dart:420:103)
#1      new ScrollPosition (package:flutter/src/widgets/scroll_position.dart:105:7)
#2      new ScrollPositionWithSingleContext (package:flutter/src/widgets/scroll_position_with_single_context.dart:56:8)
#3      ScrollableState._updatePosition (package:flutter/src/widgets/scrollable.dart:406:10)
#4      ScrollableState.didChangeDependencies (package:flutter/src/widgets/scrollable.dart:431:5)

相关代码

列表定义:

List<dynamic> RefrigCarNo = [];

ListView构建代码:

ListView.builder(
        shrinkWrap: true,
        itemCount: RefrigCarNo.length,
        itemBuilder: (BuildContext context, int index) {
          return Card(
            color: getColor(context, index),
            key: new PageStorageKey(RefrigCarNo[0].elementAt(index)), // 此处key设置存在问题
            child: ExpansionTile(
              maintainState: CollapseState,
              title: RichText(
                  textDirection: TextDirection.rtl,
                  text: TextSpan(
                      style: label_A,
                      children: [
                        TextSpan(text: 'refrigCar'),
                        TextSpan(text: ' ${RefrigCarNo[index][1].toString()} ')
                      ]
                  )
              ),
              children: [
                Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  margin: EdgeInsets.fromLTRB(0, 10, 0, 3),
                  width: PageWidth * 0.4,
                  color: Colors.white,
                  child: Column(
                    children: [
                      Text('Kg Of Material', style: label_A,),
                      AppTextField1(
                        MyController: Weight,
                        MyValidation: false,
                        typeOfInput: TextInputType.number,
                        myReadOnly: readOnlyChange,
                      ),
                    ],
                  ),
                ),
                Container(
                  margin: EdgeInsets.fromLTRB(0, 10, 0, 3),
                  width: PageWidth * 0.3,
                  color: Colors.white,
                  child: Column(
                    children: [
                      Text('Total Net', style: label_A,),
                      AppTextField1(
                        MyController: NetCalcWeight,
                        MyValidation: false,
                        typeOfInput: TextInputType.number,
                        myReadOnly: readOnlyChange,
                      ),
                    ],
                  ),
                ),
              ],
            ),
              ],
            ),
          );
        }),

删除列表项函数:

void onDeleteVar(int _index) async{ 
 setState(() {
  RefrigCarNo.removeAt(_index);
  });
}

解决方案

错误根源是PageStorageKey重复/冲突,导致滚动偏移量的存储被ExpansionTile的bool类型展开状态覆盖,进而触发类型转换错误。按以下步骤修复:

  1. 保证PageStorageKey的唯一性
    给Card和ExpansionTile分别设置独立的唯一key,避免键冲突:

    return Card(
      color: getColor(context, index),
      key: PageStorageKey('card_refrig_car_${RefrigCarNo[index][1]}'),
      child: ExpansionTile(
        key: PageStorageKey('expansion_refrig_car_${RefrigCarNo[index][1]}'),
        maintainState: CollapseState,
        // ...其他原有代码
      ),
    );
    
  2. 为每个列表项单独维护TextField控制器
    当前所有项复用同一个Weight和NetCalcWeight控制器,会导致状态混乱。修改列表结构,让每个元素自带专属控制器:

    // 添加新项的示例代码
    void addNewRefrigCar() {
      setState(() {
        RefrigCarNo.add({
          'carNo': '新车辆编号', // 替换为实际车辆标识
          'weightController': TextEditingController(),
          'netController': TextEditingController(),
        });
      });
    }
    

    然后在ListView中调用对应项的控制器:

    AppTextField1(
      MyController: RefrigCarNo[index]['weightController'],
      MyValidation: false,
      typeOfInput: TextInputType.number,
      myReadOnly: readOnlyChange,
    ),
    // ...
    AppTextField1(
      MyController: RefrigCarNo[index]['netController'],
      MyValidation: false,
      typeOfInput: TextInputType.number,
      myReadOnly: readOnlyChange,
    ),
    
  3. 删除项时清理对应PageStorage数据
    删除列表项后,手动清理该项对应的PageStorage存储,并销毁控制器避免内存泄漏:

    void onDeleteVar(int _index) {
      final carId = RefrigCarNo[_index][1];
      // 清理Card和ExpansionTile的PageStorage数据
      PageStorage.of(context)?.writeState(context, null, identifier: PageStorageKey('card_refrig_car_$carId'));
      PageStorage.of(context)?.writeState(context, null, identifier: PageStorageKey('expansion_refrig_car_$carId'));
      // 销毁控制器
      RefrigCarNo[_index]['weightController'].dispose();
      RefrigCarNo[_index]['netController'].dispose();
      setState(() {
        RefrigCarNo.removeAt(_index);
      });
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:15:35