Flutter技术入门与实战
上QQ阅读APP看书,第一时间看更新

2.3 Flutter主题

为了在整个应用中使用同一套颜色和字体样式,可以使用“主题”这种方式。定义主题有两种方式:全局主题,或使用Theme来定义应用程序局部的颜色和字体样式。事实上,全局主题只是由应用程序根MaterialApp创建的主题(Theme)。

定义一个主题后,就可以在我们自己的Widget中使用它,Flutter提供的Material Widgets将使用主题为AppBars、Buttons、Checkboxes等设置背景颜色和字体样式。

2.3.1 创建应用主题

创建主题的方法是将ThemeData提供给MaterialApp构造函数,这样就可以在整个应用程序中共享包含颜色和字体样式的主题。ThemeData的主要属性如表2-1所示。

表2-1 ThemeData属性及描述

如果没有提供主题,Flutter将创建一个默认主题。主题数据的示例代码如下:

        new MaterialApp(
          title: title,
          theme: new ThemeData(
            brightness: Brightness.dark,
            primaryColor: Colors.lightBlue[800],
            accentColor: Colors.cyan[600],
          ),
        );

2.3.2 局部主题

如果我们想在应用程序的某一部分使用特殊的颜色,那么就需要覆盖全局的主题。有两种方法可以解决这个问题:创建特有的主题数据或扩展父主题。

1.创建特有的主题数据

实例化一个ThemeData并将其传递给Theme对象,代码如下:

        new Theme(
          //创建一个特有的主题数据
          data: new ThemeData(
            accentColor: Colors.yellow,
          ),
          child: new FloatingActionButton(
            onPressed: () {},
            child: new Icon(Icons.add),
          ),
        );

2.扩展父主题

扩展父主题时无须覆盖所有的主题属性,我们可以通过使用copyWith方法来实现,代码如下:

        new Theme(
          //覆盖accentColorColors.yellow
          data: Theme.of(context).copyWith(accentColor: Colors.yellow),
          child: new FloatingActionButton(
            onPressed: null,
            child: new Icon(Icons.add),
          ),
        );

2.3.3 使用主题

主题定义好后就可以使用它了。首先,函数Theme.of(context)可以通过上下文来获取主题,方法是查找最近的主题,如果找不到就会找整个应用的主题。

下面来看一个简单的示例,应用的主题颜色定义为绿色,界面中间再加一个带有背景色的文本。

完整的例子代码如下所示:

        import 'package:flutter/foundation.dart';
        import 'package:flutter/material.dart';
        void main() {
          runApp(new MyApp());
        }
        class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            final appName = ’自定义主题’;
            return new MaterialApp(
              title: appName,
              theme: new ThemeData(
                brightness: Brightness.light, //应用程序整体主题的亮度
                primaryColor: Colors.lightGreen[600], //App主要部分的背景色
                accentColor: Colors.orange[600], //前景色(文本、按钮等)
              ),
              home: new MyHomePage(
                title: appName,
              ),
            );
          }
        }
        class MyHomePage extends StatelessWidget {
          final String title;
          MyHomePage({Key key, @required this.title}) : super(key: key);
          @override
          Widget build(BuildContext context) {
            return new Scaffold(
              appBar: new AppBar(
                title: new Text(title),
              ),
              body: new Center(
                child: new Container(
                  //获取主题的accentColor
                  color: Theme.of(context).accentColor,
                  child: new Text(
                    '带有背景颜色的文本组件’,
                    style: Theme.of(context).textTheme.title,
                  ),
                ),
              ),
              floatingActionButton: new Theme(
                //使用copyWith的方式获取accentColor
                data: Theme.of(context).copyWith(accentColor: Colors.grey),
                child: new FloatingActionButton(
                  onPressed: null,
                  child: new Icon(Icons.computer),
                ),
              ),
            );
          }
        }

自定义主题的效果如图2-1所示。

图2-1 自定义主题效果图