Flutter主题Theme的详解(创建&使用&获取)
为了在整个应用中共享颜色和字体样式,我们可以使用主题。定义主题有两种方式:全局主题或使用Theme来定义应用程序局部的颜色和字体样式。事实上,全局主题只是由应用程序根MaterialApp创建的Theme。
定义一个主题后,我们可以在我们自己的Widgets中使用它。另外,Flutter提供的Material Widgets将使用我们的主题为AppBars、Buttons、Checkboxes等设置背景颜色和字体样式。
创建主题
可以通过配置ThemeData类轻松更改应用程序的主题。
ThemeData
ThemeData是Material Design Widget库的主题数据,Material库的Widget需要遵守相应的设计规范,而这些规范可自定义(部分),所以我们可以通过ThemeData来自定义应用主题,我们可以通过Theme.of方法来获取当前的ThemeData。
ThemeData部分数据:
ThemeData({
Brightness brightness, //深色还是浅色
MaterialColor primarySwatch, //主题颜色样本,见下面介绍
Color primaryColor, //主色,决定导航栏颜色
Color accentColor, //次级色,决定大多数Widget的颜色,如进度条、开关等。
Color cardColor, //卡片颜色
Color dividerColor, //分割线颜色
ButtonThemeData buttonTheme, //按钮主题
Color cursorColor, //输入框光标颜色
Color dialogBackgroundColor,//对话框背景颜色
String fontFamily, //文字字体
TextTheme textTheme,// 字体主题,包括标题、body等文字样式
IconThemeData iconTheme, // Icon的默认样式
TargetPlatform platform, //指定平台,应用特定平台控件风格
...
})
设置整个应用的主题
例如,为了在整个应用程序中共享包含颜色和字体样式的主题,我们可以提供ThemeData给MaterialApp的构造函数。
示例:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'budaye',
theme: new ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.white,
accentColor: Colors.cyan[600],
),
home: new RandomWords(),
);
}}
局部主题
如果我们想在应用程序的一部分中覆盖应用程序的全局的主题,我们可以将要覆盖得部分封装在一个Theme Widget中。
有两种方法可以解决这个问题:创建特有的ThemeData或扩展父主题。
1. 创建特有的 ThemeData
如果我们不想继承任何应用程序的颜色或字体样式,我们可以通过new ThemeData()创建一个实例并将其传递给Theme Widget。
new Theme(
// Create a unique theme with "new ThemeData"
data: new ThemeData(
accentColor: Colors.yellow,
),
child: new FloatingActionButton(
onPressed: () {},
child: new Icon(Icons.add),
),
);
2. 扩展父主题
扩展父主题时无需覆盖所有的主题属性,我们可以通过使用copyWith方法来实现。
new Theme(
// Find and Extend the parent theme using "copyWith". Please see the next
// section for more info on `Theme.of`.
data: Theme.of(context).copyWith(accentColor: Colors.yellow),
child: new FloatingActionButton(
onPressed: null,
child: new Icon(Icons.add),
),
);
使用主题
1. 应用主题的使用
应用主题的使用上面已经介绍了,这里不做重复介绍了。
2. 局部主题的使用
在想要应用局部主题的widget外部,包裹Theme来实现:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// backgroundColor: Colors.green, //设置标题栏的背景颜色
title: new Title(
child: new Text(
'这是一个标题',
),
color: Colors.white,
),
),
body: new Theme(
// Create a unique theme with "new ThemeData"
data: new ThemeData(
// accentColor: Colors.yellow,
),
child: new FloatingActionButton(
onPressed: () {},
child: new Icon(Icons.add),
),
),
);
}
}
3. 主题的获取
现在我们已经定义了一个主题,我们可以在Widget的build方法中通过Theme.of(context)函数使用它。
Theme.of(context)将查找Widget树并返回树中最近的Theme。如果我们的Widget之上有一个单独的Theme定义,则返回该值。如果不是,则返回App主题。
new Container(
color: Theme.of(context).accentColor,
child: new Text(
'Text with a background color',
style: Theme.of(context).textTheme.title,
),
);