如何将不同的主题应用到Flutter应用程序的各个部分(包括子路线)?

m1m5dgzv  于 2022-11-17  发布在  Flutter
关注(0)|答案(1)|浏览(130)

我的应用程序有不同的部分,我希望他们有不同的主题颜色,包括导航中的所有子路线。
但是如果我使用主题,它就不会应用到子路径中的小部件。我也尝试过使用嵌套的MaterialApps,但是这不起作用,因为我不能弹出回根菜单。我不希望必须将Color参数传递到所有屏幕。我该怎么办?
下面是一个测试代码:

import 'package:flutter/material.dart';

main() {
  runApp(MaterialApp(home: _Test()));
}

class _Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              child: Text('Red section'),
              onPressed: () {
                Navigator.push(context, MaterialPageRoute(
                  builder: (context) {
                    return Theme(
                      data: ThemeData(colorScheme: ColorScheme.light(primary: Colors.red)),
                      child: _TestSubRoute(),
                    );
                  },
                ));
              },
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              child: Text('Green section'),
              onPressed: () {
                Navigator.push(context, MaterialPageRoute(
                  builder: (context) {
                    return Theme(
                      data: ThemeData(colorScheme: ColorScheme.light(primary: Colors.green)),
                      child: _TestSubRoute(),
                    );
                  },
                ));
              },
            ),
          ],
        ),
      ),
    );
  }
}

class _TestSubRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.2),
      appBar: AppBar(
        title: Text('Should keep the same color through the navigation...'),
        actions: [
          IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) {
                  return AlertDialog(
                    title: Text('Hello'),
                    actions: [
                      TextButton(
                        child: Text('OK'),
                        onPressed: () => Navigator.pop(context),
                      ),
                    ],
                  );
                },
              );
            },
          ),
        ],
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Push...'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => _TestSubRoute()),
            );
          },
        ),
      ),
    );
  }
}
bgibtngc

bgibtngc1#

您可以使用Theme小部件为小部件树的一部分设置一个自定义的不同ThemeData,如下所示:

Theme(
  data: ThemeData.light().copyWith(
    primaryColor: Colors.purple,
  ),
  child: YourWidget(),
);

在Flutter中,Theme是一个InheritedWidget,因此您设置为data属性的ThemeData将应用于子属性的整个子树,即使您将小部件分成多个小部件...,它们也将使用context引用小部件树中最近的Theme小部件。
MaterialApp有一个默认的嵌套在里面,所以当我们执行:

Theme.of(context).primaryColor,

它从MaterialApp的嵌套Theme中得到primaryColor,因为它是最接近的。
但是当您像上面的例子一样将主题小部件指定到小部件树的一部分时,YourWidget()内的任何内容都将引用该ThemeData
请参阅https://api.flutter.dev/flutter/material/Theme-class.html

相关问题