在Flutter开发中,通过定义 Theme,复用颜色和字体样式,从而让整个app的设计看起来更一致。

一. Theme主题的使用

Theme分为:全局Theme和局部Theme
主题有两个作用:

  • 设置了主题之后,某些Widget会自动使用主题的样式(比如AppBar的颜色)
  • 将某些样式放到主题中统一管理,在应用程序的其它地方直接引用

    1.1. 全局Theme

    全局Theme会影响整个app的颜色和字体样式,只需要向MaterialApp构造器传入 ThemeData 即可。

  • 如果没有设置Theme,Flutter将会使用预设的样式

    1. class MyApp extends StatelessWidget {
    2. // This widget is the root of your application.
    3. @override
    4. Widget build(BuildContext context) {
    5. return MaterialApp(
    6. title: 'Flutter Demo',
    7. theme: ThemeData(
    8. // 1.亮度: light-dark
    9. brightness: Brightness.light,
    10. // 2.primarySwatch: primaryColor/accentColor的结合体
    11. primarySwatch: Colors.red,
    12. // 3.主要颜色: 导航/底部TabBar
    13. primaryColor: Colors.pink,
    14. // 4.次要颜色: FloatingActionButton/按钮颜色
    15. accentColor: Colors.orange,
    16. // 5.卡片主题
    17. cardTheme: CardTheme(
    18. color: Colors.greenAccent,
    19. elevation: 10,
    20. shape: Border.all(width: 3, color: Colors.red),
    21. margin: EdgeInsets.all(10)
    22. ),
    23. // 6.按钮主题
    24. buttonTheme: ButtonThemeData(
    25. minWidth: 0,
    26. height: 25
    27. ),
    28. // 7.文本主题
    29. textTheme: TextTheme(
    30. title: TextStyle(fontSize: 30, color: Colors.blue),
    31. display1: TextStyle(fontSize: 10),
    32. )
    33. ),
    34. home: HYHomePage(),
    35. );
    36. }
    37. }

    1.2. 局部Theme

    如果某个Widget不希望直接使用全局的Theme,希望自己来定义:

  • 非常简单,只需要在Widget的父节点包裹一下Theme即可

创建另外一个新的页面,页面中使用新的主题:

  • 在新的页面的Scaffold外,包裹了一个Theme,并且设置data为一个新的ThemeData

    1. class HYSecondPage extends StatelessWidget {
    2. @override
    3. Widget build(BuildContext context) {
    4. return Theme(
    5. data: ThemeData(),
    6. child: Scaffold(
    7. ),
    8. );
    9. }
    10. }

    很多时候并不是想完全使用一个新的主题,而且在之前的主题基础之上进行修改:

    1. class HYSecondPage extends StatelessWidget {
    2. @override
    3. Widget build(BuildContext context) {
    4. return Theme(
    5. data: Theme.of(context).copyWith(
    6. primaryColor: Colors.greenAccent
    7. ),
    8. child: Scaffold(
    9. ),
    10. );
    11. }
    12. }

    二. 暗黑Theme适配

    2.1. darkTheme

    MaterialApp中有theme和dartTheme两个参数:

    1. class MyApp extends StatelessWidget {
    2. // This widget is the root of your application.
    3. @override
    4. Widget build(BuildContext context) {
    5. return MaterialApp(
    6. title: 'Flutter Demo',
    7. theme: ThemeData.light(),
    8. darkTheme: ThemeData.dark(),
    9. home: HYHomePage(),
    10. );
    11. }
    12. }

    2.2. 开发中适配

    在开发中,为了能适配两种主题(设置是更多的主题),我们可以封装一个AppTheme

  • 1.公共的样式抽取成常量

  • 2.封装一个亮色主题
  • 3.封装一个暗黑主题 ```dart import’package:flutter/material.dart’;

class AppTheme { // 1.抽取相同的样式 staticconstdouble _titleFontSize = 20;

// 2.亮色主题 staticfinal ThemeData lightTheme = ThemeData( primarySwatch: Colors.pink, primaryTextTheme: TextTheme( title: TextStyle( color: Colors.yellow, fontSize: _titleFontSize ) ), textTheme: TextTheme( body1: TextStyle(color: Colors.red) ) );

// 3.暗黑主题 staticfinal ThemeData darkTheme = ThemeData( primaryColor: Colors.grey, primaryTextTheme: TextTheme( title: TextStyle( color: Colors.white, fontSize: _titleFontSize ) ), textTheme: TextTheme( title: TextStyle(color: Colors.white), body1: TextStyle(color: Colors.white70) ) ); }

  1. 在MaterialApp中,可以决定使用哪一个主题:
  2. ```dart
  3. class MyApp extends StatelessWidget {
  4. // This widget is the root of your application.
  5. @override
  6. Widget build(BuildContext context) {
  7. return MaterialApp(
  8. title: 'Flutter Demo',
  9. theme: AppTheme.lightTheme,
  10. darkTheme: AppTheme.darkTheme,
  11. home: HYHomePage(),
  12. );
  13. }
  14. }