Flutter Theme学习和使用

2,852 阅读3分钟

试用了一下Flutter的Theme,真香,特别是对于创建小而美的APP来说,控制集中,提供了整体样式修改方案。

更多详细文章关注微信公众号:Flutter入门

Flutter入门

首先先看看官方ThemeData的构造函数:

太多,选择几个吧

accentColor-Color类型,前景色(文本、按钮等)

accentColorBrightness-Brightness类型,accentColor的亮度,用于确定放置在突出颜色顶部的文本和图标颜色

backgroundColor-Color类型,与primaryColor对比的颜色(用作进度条的剩余部分)

buttonTheme-ButtonThemeData类型,定义了按钮等空间的默认配置

cardColor-Color类型,Material被用作Card时的颜色

dialogBackgroundColor-Color类型,dialog元素的背景色

disableColor-Color类型,用于Widget无效的颜色

dividerColor-Color类型,Dividers和PopupMenuDividers的颜色,也用于ListTiles中间和DataTables中间

errorColor-Color类型,用于输入验证错误的颜色,例如在TextField中

highlightColor-Color类型,用于类似墨水喷溅动画或指示菜单被选中的高亮色

hintColor-Color类型,用于提示文本占位符颜色,如TextField中

Platforn-TargetPlatform类型,Widget需要适配的目标类型

primaryColor-Color类型,App主要部分的背景色

primaryColorBrightness-Brightness类型,primaryColor的亮度

primaryColorDark-Color类型,primaryColor的较暗版本

primaryColorLight-Color类型,primaryColor的较亮版本

textTheme-TextTheme类型,与卡片和画布对比的文本样式

runtimeType-Type类型,便是对象运行时类型

使用:

自定义一个ThemeData,可以是一个常量

final ThemeData defaultTheme = new ThemeData(
  accentColor: Colors.red,
  accentColorBrightness: Brightness.dark,
  primaryColor: Colors.red,
  primarySwatch: Colors.orange,
  buttonTheme: ButtonThemeData(
    buttonColor: Colors.orange,
    padding: EdgeInsets.all(7),
  ),
  textTheme: TextTheme(
    title: TextStyle(color: Colors.black, fontSize: 33),
    display1: TextStyle(color: Colors.black, fontSize: 40),
  ),
);

在使用的时候在最外层的MaterialApp的theme添加自定义的theme(main.dart),这样就会创建一个全局的theme

theme: defaultTheme

这些在新加的页面中,login.dart、Home.dart中整个theme就会变化

Widget会向上查找,使用离它层级最近的Theme

对于某一个Widget想使用特定的theme的话:

new Theme(
  data: ThemeData(
    accentColor: Colors.red,
  ),
  child: FloatingActionButton(
    onPressed: _incrementCounter,
    tooltip: 'Increment',
    child: Icon(Icons.add),
  ),
)

看是很完美,官方都是用到了FloatingActionButton上,因为FloatingActionButton是默认使用Theme的builder的,但是用到一个Text上,没效果,这是因为context错了,使用Builder

new Theme(
  data: new ThemeData(
    primaryColor: Colors.red,
    accentColor: Colors.red,
    textTheme: TextTheme(
      title: TextStyle(color: Colors.black),
    ),
  ),
  child: Builder(
    builder: (context) {
      return Text(
        '登录',
        style: Theme.of(context).textTheme.title,
      );
    },
  ),
)

但是其他想和主Theme一样,只想改动一个属性咋办

new Theme(
  data: Theme.of(context).copyWith(
    textTheme: Theme.of(context).textTheme.copyWith(
          title: Theme.of(context)
              .textTheme
              .title
              .copyWith(color: Colors.white),
        ),
  ),
  child: Builder(
    builder: (context) {
      return Text(
        '登录',
        style: Theme.of(context).textTheme.title,
      );
    },
  ),
)

这样就只改了title的颜色了,只是改里层的属性的时候,需要多次copyWith

顺便,还有页面之间传递数据

构造函数的样子看着不是很习惯,拓展性不是很强,想和Android一样的Bundle携带数据多好。

Navigator.pushNamed(context, '/Home', arguments: 'String~~~').then((data) {
  print(data);
});

通过argument携带数据

下一个页面接收数据

dynamic obj = ModalRoute.of(context).settings.arguments;

返回数据在then回调里面

Navigator.of(context).pop('ok~~~')

会遇到的问题,MaterialApp最好只用一个,其实应该强制,除非其他需求。在这里添加router、theme,否则会发现router找不到或者theme无效

代码已上传GitHub