Flutter 主题

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

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

创建应用主题

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

Flutter 主题

Flutter 主题

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

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

局部主题

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

1.创建特有的主题数据
实例化一个ThemeData并将其传递给Theme对象,代码如下:

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

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

使用主题

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

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

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

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';


void main() {
    runApp(MyApp());
}


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appName = '自定义主题';


    return MaterialApp(
      title: appName,
      // 主题配置
      theme: ThemeData(
        // 应用程序整体主题的亮度
        brightness: Brightness.light,
        // App主要部分的背景色
        primaryColor: Colors.lightGreen[600],
        // 前景色(文本、按钮等)
        accentColor: Colors.orange[600],
      ),
      home: MyHomePage(
        title: appName,
      ),
    );
  }
}


class MyHomePage extends StatelessWidget {
  // 标题
  final String title;
  //接收title值key为widget的唯一标识
  MyHomePage({Key key, @required this.title}) : super(key: key);


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Container(
          // 获取主题的accentColor
              color: Theme.of(context).accentColor,
              child: Text(
                '带有背景颜色的文本组件',
                // 获取主题的文本样式
                style: Theme.of(context).textTheme.title,
              ),
            ),
          ),
          floatingActionButton: Theme(
            // 使用copyWith的方式获取accentColor
            data: Theme.of(context).copyWith(accentColor: Colors.grey),
            child: FloatingActionButton(
              onPressed: null,
              child: Icon(Icons.computer),
            ),
          ),
        );
      }
    }

这里我们第一次用到了Key。Flutter里Key是每一个Widget的唯一身份标识,它是在组件创建及渲染时生成的。上面的代码把Key作为参数传入Widgth中,则此Widget会根据指定的名字生成Key,Key是一个可选参数。

Flutter是受React启发的,参考了Virtual Dom(虚拟Dom)的Diff算法。在Diff的过程中,如果节点有Key进行比对,则能够最大限度重用已有的节点(特别是在有列表渲染的场景中)。总之,这里我们可以知道Key能够提高性能,所以每个Widget都会构建方法,也都会有一个Key参数可选,贯穿着整个框架。Key派生出Localkey和Globalkey,二者的用途如下所示:

  • Localkey :直接继承自Key,它应用于拥有相同父Element的组件进行比较的情况。Localkey派生出了许多子类,如ValueKey、ObjectKey、UniqueKey。
  • GlobalKey:可以通过GlobalKey找到持有该GlobalKey的Widget、State和Element。注意,GlobalKey是非常昂贵的,需要谨慎使用。

自定义主题的效果如图所示。
Flutter 主题

赞(0)

评论 抢沙发

评论前必须登录!