Flutter 添加到 List<Widget> 由于类型问题而崩溃

Flutter add to List<Widget> crashes beacuase of type issues

我有一个问题我不明白。

   Widget build(BuildContext context) {
    List<Widget> menuList = menuCategories.map((category) {
      return ExpansionTile(
          title: CustomExpansionTileHeader(
            icon: category.icon,
            label: category.label,
          ),
          children: category.children
              .map((item) => ListTile(
                    title: Text(item.label),
                    onTap: item.onTap,
                  ))
              .toList());
    }).toList();
    print(menuList);
    menuList.insert(
        0,
        DrawerHeader(
            child: Text(
              '',
              style: TextStyle(color: Colors.white, fontSize: 25),
            ),
            decoration: BoxDecoration(
              color: Colors.green,
              // image: DecorationImage(
              // fit: BoxFit.fill,
              // image: AssetImage('assets/images/cover.jpg'))),
            )));
    return Drawer(
      child: ListView(padding: EdgeInsets.zero, children: menuList

如您所见,我正在尝试使用一些 ExpansionTile 小部件创建列表类型小部件,但还将 DrawerHeader 添加为索引 0。之后,我想 return 列表作为子列表中的抽屉小部件。

当我打印 menuList(在将 DrawerHeader 添加到列表之前)时,它打印 [ExpansionTile、ExpansionTile、ExpansionTile、ExpansionTile],当我打印 menuList.runtimeType 时,我得到 List type ExpansionTile。 这是我不明白的部分。该列表应该是小部件列表,但不知何故发生了变化。

当我将 DrawerHeader 添加到列表时,这会导致崩溃,因为它的类型不同。

如果它很重要,我正在构建 Flutter 网络应用程序。

请帮忙:)

当您执行 List<Widget> menuList = menuCategories.map((category) { 时,请使用通用字段指定类型。 Dart 错误地推断您希望此可迭代对象的类型为 ExpansionTile.

List<Widget> menuList = menuCategories.map<Widget>((category) {

更明确地告诉 dart 你想要它是什么类型。

The answer from @Christopher Moore is better than the approach mentioned below.

映射后的 tooList() 调用总是 returns List<ExpansionTile>。这更像是 Dart 类型的安全机制。因此,与其插入到现有列表中,不如将其收集为单独的列表并使用扩展运算符并将这些元素添加到新列表中,如下所示。 dartpad 中提供了实时版本 here

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Drawer Demo'),
        ),
        drawer: MyWidget(),
        body: Center(
          child: Text('Hello'),
        ),
      ),
    );
  }
}

class Item {
  String label;
  Function onTap;
  Item({this.label, this.onTap});
}

class Category {
  Icon icon;
  String label;
  List<Item> children;
  Category({this.icon, this.label, this.children});
}

class MyWidget extends StatelessWidget {
  final menuCategories = [
    Category(
      icon: Icon(Icons.ac_unit),
      label: 'ac_unit',
      children: [
        Item(label: 'Voltas'),
        Item(label: 'Haier'),
      ],
    ),
    Category(
      icon: Icon(Icons.computer),
      label: 'computers',
      children: [
        Item(label: 'HP'),
        Item(label: 'Dell'),
      ],
    ),
  ];
  @override
  Widget build(BuildContext context) {
    final categoryList = menuCategories.map((Category category) {
      return ExpansionTile(
          title: ListTile(
            title: Text(category.label),
          ),
          children: category.children
              .map((item) => ListTile(
                    title: Text(item.label),
                    onTap: item.onTap,
                  ))
              .toList());
    }).toList();

    List<Widget> menuList = [
      DrawerHeader(
        child: Text(
          'Categories',
          style: TextStyle(color: Colors.white, fontSize: 25),
        ),
        decoration: BoxDecoration(
          color: Colors.green,
          // image: DecorationImage(
          // fit: BoxFit.fill,
          // image: AssetImage('assets/images/cover.jpg'))),
        ),
      ),
      ...categoryList
    ];
    return Drawer(
        child: ListView(padding: EdgeInsets.zero, children: menuList));
  }
}

您可以在普通的 dartpad 中测试以下代码,以验证与您所看到的相同的问题。

void main() {
  List<A> menus = [B('s'),B('fd')].toList();
  menus.insert(0, C('1'));
  print(menus);
}

class A {
  
}

class B extends A {
  String label;
  B(this.label);
}

class C extends A {
  String label;
  C(this.label);
}