List.map().toList() 生成 List<Set<Widget> 而不是 List<Widget>

问题描述 投票:0回答:1

我正在学习 Flutter 的诀窍。 教程很棒,但是当我尝试用从列表生成的开关和导航栏替换硬编码的侧边栏开关和导航栏时,我遇到了一堆打字问题。基本上,我想由此生成它们:

var appPages = [
  {
    'name': 'Header 1',
    'icon': const Icon(Icons.cloud_upload),
    'content': const PlaceholderPage(
        placeholderText: '<h1>Test Header 1</h1><br/>Lorem ipsum.')
  },
  {
    'name': 'Header 2',
    'icon': const Icon(Icons.delete_sweep_outlined),
    'content': const PlaceholderPage(
        placeholderText: '<h2>Test Header 2</h2><br/>Lorem ipsum.')
  },
  {
    'name': 'Bold Italics',
    'icon': const Icon(Icons.bloodtype),
    'content': const PlaceholderPage(
        placeholderText: '<i>Test <b>Bold</b> Italics</i><br/>Lorem ipsum.')
  },
];

然后代替

    Widget page;
    switch (selectedIndex) {
      case 0:
        page = const PlaceholderPage(placeholderText: '<h1>Test Header 1</h1><br/>Lorem ipsum.');
        break;
      case 1:
        page = const PlaceholderPage(placeholderText: '<h2>Test Header 2</h2><br/>Lorem ipsum.');
        break;
      case 2:
        page = const PlaceholderPage(placeholderText: '<i>Test <b>Bold</b> Italics</i><br/>Lorem ipsum.');
        break;
      default:
        throw UnimplementedError('no widget for $selectedIndex');
    }

我会:

    var page = appPages[selectedIndex]['content'] as Widget?;

而不是列出每个 NavigationRailDestination:

                  destinations:
                    const [
                      NavigationRailDestination(
                        icon: Icon(Icons.cloud_upload),
                        label: Text('Header 1')),
                      NavigationRailDestination(
                        icon: Icon(Icons.delete_sweep_outlined),
                        label: Text('Header 2')),
                      NavigationRailDestination(
                        icon: Icon(Icons.bloodtype),
                        label: Text('Bold Italics')),
                  ],

我想要这样的东西:

                  destinations:
                      appPages.map((e) => {
                            NavigationRailDestination(
                                icon: e['icon'] as Widget, label: Text(e['name'] as String))
                          }).toList() as List<NavigationRailDestination>

但目前这失败了

_TypeError (type 'List<Set<NavigationRailDestination>>' is not a subtype of type 'List<NavigationRailDestination>' in type cast)

有任何修复此错误的方法,或者更优雅的方法吗?

提前致谢!

pubspec.yaml:

name: sidebar_test
publish_to: 'none'
version: 0.1.0

environment:
  sdk: '>=3.3.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0
  material_design_icons_flutter: ^7.0.0
  styled_text: ^8.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0

flutter:
  uses-material-design: true

main.dart:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:styled_text/styled_text.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

var appName = 'Sidebar Test';

var appTheme = ThemeData(
  useMaterial3: true,
  colorScheme: ColorScheme.fromSeed(seedColor: const Color(0x006AAE3F)),
);

var appStyleTags = {
  'h1': StyledTextTag(
      style: TextStyle(
          height: 2, fontSize: 50, color: appTheme.colorScheme.primary)),
  'h2': StyledTextTag(
      style: appTheme.textTheme.displayMedium!.copyWith(
    color: appTheme.colorScheme.primary,
  )),
  'b': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold)),
  'i': StyledTextTag(style: const TextStyle(fontStyle: FontStyle.italic)),
};

var appPages = [
  {
    'name': 'Header 1',
    'icon': const Icon(Icons.cloud_upload),
    'content': const PlaceholderPage(
        placeholderText: '<h1>Test Header 1</h1><br/>Lorem ipsum.')
  },
  {
    'name': 'Header 2',
    'icon': const Icon(Icons.delete_sweep_outlined),
    'content': const PlaceholderPage(
        placeholderText: '<h2>Test Header 2</h2><br/>Lorem ipsum.')
  },
  {
    'name': 'Bold Italics',
    'icon': const Icon(Icons.bloodtype),
    'content': const PlaceholderPage(
        placeholderText: '<i>Test <b>Bold</b> Italics</i><br/>Lorem ipsum.')
  },
];

var appPagesFirst = appPages[0];
// var appPagesList = appPages.entries.toList();

void main() {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: appName,
        theme: appTheme,
        home: const HomePage(),
        debugShowCheckedModeBanner: false,
        restorationScopeId: appName,
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var selectedIndex = 0;
  bool? navExtended;

  @override
  Widget build(BuildContext context) {
    var colorScheme = Theme.of(context).colorScheme;

    // Use appPages
    var page = appPages[selectedIndex]['content'] as Widget?;

    // Instead of switch:
    // Widget page;
    // switch (selectedIndex) {
    //   case 0:
    //     page = const PlaceholderPage(placeholderText: '<h1>Test Header 1</h1><br/>Lorem ipsum.');
    //     break;
    //   case 1:
    //     page = const PlaceholderPage(placeholderText: '<h2>Test Header 2</h2><br/>Lorem ipsum.');
    //     break;
    //   case 2:
    //     page = const PlaceholderPage(placeholderText: '<i>Test <b>Bold</b> Italics</i><br/>Lorem ipsum.');
    //     break;
    //   default:
    //     throw UnimplementedError('no widget for $selectedIndex');
    // }

    // The container for the current page, with its background color
    // and subtle switching animation.
    var mainArea = ColoredBox(
      color: colorScheme.surfaceVariant,
      child: AnimatedSwitcher(
        duration: const Duration(milliseconds: 200),
        child: page,
      ),
    );

    return Scaffold(
      body: LayoutBuilder(
        builder: (context, constraints) {
          return Row(
            children: [
              SafeArea(
                child: NavigationRail(
                  selectedIndex: selectedIndex,
                  onDestinationSelected: (value) {
                    setState(() {
                      selectedIndex = value;
                    });
                  },
                  extended: navExtended != null
                      ? navExtended ?? true
                      : constraints.maxWidth >= 600,
                  leading: StyledText(
                    text: '<b>$appName</b>',
                    tags: appStyleTags,
                  ),
                  trailing: Expanded(
                    child: Align(
                      alignment: Alignment.bottomLeft,
                      child: IconButton(
                        icon: Icon((navExtended ?? true)
                            ? MdiIcons.arrowCollapseLeft
                            : MdiIcons.arrowExpandRight),
                        onPressed: () {
                          setState(() {
                            setState(
                                () => navExtended = !(navExtended ?? true));
                          });
                        },
                      ),
                    ),
                  ),
                  destinations:
                      // Use appPages
                      appPages.map((e) => {
                            NavigationRailDestination(
                                icon: e['icon'] as Widget, label: Text(e['name'] as String))
                          }).toList() as List<NavigationRailDestination>
                      // Instead of
                      // const [
                      //   NavigationRailDestination(
                      //     icon: Icon(Icons.cloud_upload),
                      //     label: Text('Header 1')),
                      //   NavigationRailDestination(
                      //     icon: Icon(Icons.delete_sweep_outlined),
                      //     label: Text('Header 2')),
                      //   NavigationRailDestination(
                      //     icon: Icon(Icons.bloodtype),
                      //     label: Text('Bold Italics')),
                      // ],
                ),
              ),
              Expanded(child: mainArea),
            ],
          );
          // }
        },
      ),
    );
  }
}

class PlaceholderPage extends StatelessWidget {
  const PlaceholderPage({
    super.key,
    required this.placeholderText,
  });

  final String placeholderText;

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      const Spacer(),
      Card(
        child: Padding(
            padding: const EdgeInsets.all(20),
            child: AnimatedSize(
                duration: const Duration(milliseconds: 200),
                child: StyledText(text: placeholderText, tags: appStyleTags))),
      ),
      const Spacer(),
    ]);
  }
}
flutter dart typing
1个回答
0
投票

Dart 的匿名函数是用括号和花括号定义的:

(s) { print(s); }
,但如果它由单个语句组成,你可以使用右箭头(
(s) => print(s);
,然后你必须省略花括号,否则事情会崩溃,或者更糟,被解释为一个集合。D'oh.

只需删除它们(或箭头)即可:

                  destinations:
                      appPages.map((e) =>
                            NavigationRailDestination(
                                icon: e['icon'] as Widget, label: Text(e['name'] as String))
                          ).toList() as List<NavigationRailDestination>

工作沙箱:https://flutlab.io/editor/2041e217-a3b9-482f-bc3e-45c0a36895fd

© www.soinside.com 2019 - 2024. All rights reserved.