Flutter 主题,为了在整个应用中使用同一套颜色和字体样式,可以使用主题这种方式。定义主题有两种方式:全局主题,或使用Theme来定义应用程序局部的颜色和字体样式。事实上,全局主题只是由应用程序根MaterialApp
创建的主题。
定义一个主题后,就可以在我们自己的Widget中使用它,Flutter提供的Material Widgets将使用主题为AppBars
、Buttons
、Checkboxes
等设置背景颜色和字体样式。
创建应用主题
创建主题的方法是将ThemeData提供给MaterialApp构造函数,这样就可以在整个应用程序中共享包含颜色和字体样式的主题。ThemeData的主要属性如表所示:
如果没有提供主题,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是非常昂贵的,需要谨慎使用。
自定义主题的效果如图所示。
评论前必须登录!
注册