主题定制

视觉效果是易变的,我们将这些变化的部分抽离出来,把提供不同视觉效果的资源和配置按照主题进行归类,整合到一个统一的中间层去管理,这样我们就能实现主题的管理和切换了。

Flutter 中由 ThemeData 来统一管理主题的配置信息.

通过 ThemeData 来自定义应用主题,我们可以实现 App 全局范围,或是 Widget 局部范围的样式切换。接下来,我便分别与你讲述这两种范围的主题切换。

全局统一的视觉风格定制

在 Flutter 中,应用程序类 MaterialApp 的初始化方法,为我们提供了设置主题的能力。我们可以通过参数 theme,选择改变 App 的主题色、字体等,设置界面在 MaterialApp 下的展示样式。

  1. MaterialApp(
  2. title: 'Flutter Demo',//标题
  3. theme: ThemeData(//设置主题
  4. brightness: Brightness.dark,//设置明暗模式为暗色
  5. accentColor: Colors.black,//(按钮)Widget前景色为黑色
  6. primaryColor: Colors.cyan,//主色调为青色
  7. iconTheme:IconThemeData(color: Colors.yellow),//设置icon主题色为黄色
  8. textTheme: TextTheme(body1: TextStyle(color: Colors.red))//设置文本颜色为红色
  9. ),
  10. home: MyHomePage(title: 'Flutter Demo Home Page'),
  11. );

局部独立的视觉风格定制

在 Flutter 中,我们可以使用 Theme 来对 App 的主题进行局部覆盖。Theme 是一个单子 Widget 容器,与 MaterialApp 类似的,我们可以通过设置其 data 属性,对其子 Widget 进行样式定制:

  • 如果我们不想继承任何 App 全局的颜色或字体样式,可以直接新建一个 ThemeData 实例,依次设置对应的样式;
  • 而如果我们不想在局部重写所有的样式,则可以继承 App 的主题,使用 copyWith 方法,只更新部分样式。
  1. // 新建主题
  2. Theme(
  3. data: ThemeData(iconTheme: IconThemeData(color: Colors.red)),
  4. child: Icon(Icons.favorite)
  5. );
  6. // 继承主题
  7. Theme(
  8. data: Theme.of(context).copyWith(iconTheme: IconThemeData(color: Colors.green)),
  9. child: Icon(Icons.feedback)
  10. );

除了定义 Material Design 规范中那些可自定义部分样式外,主题的另一个重要用途是样式复用。

比如,如果我们想为一段文字复用 Materia Design 规范中的 title 样式,或是为某个子 Widget 的背景色复用 App 的主题色,我们就可以通过 Theme.of(context) 方法,取出对应的属性,应用到这段文字的样式中。

Theme.of(context) 方法将向上查找 Widget 树,并返回 Widget 树中最近的主题 Theme。如果 Widget 的父 Widget 们有一个单独的主题定义,则使用该主题。如果不是,那就使用 App 全局主题。
_

  1. Container(
  2. color: Theme.of(context).primaryColor,//容器背景色复用应用主题色
  3. child: Text(
  4. 'Text with a background color',
  5. style: Theme.of(context).textTheme.title,//Text组件文本样式复用应用文本样式
  6. ));

分平台主题定制

有时候,为了满足不同平台的用户需求,我们希望针对特定的平台设置不同的样式。比如,在 iOS 平台上设置浅色主题,在 Android 平台上设置深色主题。面对这样的需求,我们可以根据 defaultTargetPlatform 来判断当前应用所运行的平台,从而根据系统类型来设置对应的主题。

  1. // iOS浅色主题
  2. final ThemeData kIOSTheme = ThemeData(
  3. brightness: Brightness.light,//亮色主题
  4. accentColor: Colors.white,//(按钮)Widget前景色为白色
  5. primaryColor: Colors.blue,//主题色为蓝色
  6. iconTheme:IconThemeData(color: Colors.grey),//icon主题为灰色
  7. textTheme: TextTheme(body1: TextStyle(color: Colors.black))//文本主题为黑色
  8. );
  9. // Android深色主题
  10. final ThemeData kAndroidTheme = ThemeData(
  11. brightness: Brightness.dark,//深色主题
  12. accentColor: Colors.black,//(按钮)Widget前景色为黑色
  13. primaryColor: Colors.cyan,//主题色Wie青色
  14. iconTheme:IconThemeData(color: Colors.blue),//icon主题色为蓝色
  15. textTheme: TextTheme(body1: TextStyle(color: Colors.red))//文本主题色为红色
  16. );
  17. // 应用初始化
  18. MaterialApp(
  19. title: 'Flutter Demo',
  20. theme: defaultTargetPlatform == TargetPlatform.iOS ? kIOSTheme : kAndroidTheme,//根据平台选择不同主题
  21. home: MyHomePage(title: 'Flutter Demo Home Page'),
  22. );