Theme
组件可以为Material APP定义主题数据(ThemeData)。Material组件库里很多组件都使用了主题数据,如导航栏颜色、标题字体、Icon样式等。Theme
内会使用InheritedWidget
来为其子树共享样式数据。
ThemeData
ThemeData
用于保存是Material组件库的主题数据,Material组件需要遵守相应的设计规范,而这些规范可自定义部分都定义在ThemeData
中了,所以可以通过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, // 指定平台,应用特定平台控件风格
...
})
代码示例:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
// primarySwatch传入不是Color, 而是MaterialColor(包含了primaryColor和accentColor)
primarySwatch: Colors.red,
// primaryColor: 单独设置导航和TabBar的颜色
primaryColor: Colors.orange,
// accentColor: 单独设置FloatingActionButton、Switch等widget
accentColor: Colors.green,
// Button的主题
buttonTheme: ButtonThemeData(
height: 25, minWidth: 10, buttonColor: Colors.yellow),
// Card的主题
cardTheme: CardTheme(color: Colors.greenAccent, elevation: 10),
// Text的主题
textTheme: TextTheme(
bodyText2: TextStyle(fontSize: 16, color: Colors.red),
bodyText1: TextStyle(fontSize: 20, color: Colors.blue),
headline1: TextStyle(fontSize: 14),
headline2: TextStyle(fontSize: 16),
headline3: TextStyle(fontSize: 18),
headline4: TextStyle(fontSize: 20),
),
),
home: ThemeDemo(),
);
}
}
class ThemeDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("首页")),
body: Center(
child: Column(
children: <Widget>[
Text("Hello World"),
Text(
"Hello World",
style: TextStyle(fontSize: 14),
),
Text(
"Hello World",
style: TextStyle(fontSize: 20),
),
Text(
"Hello World",
style: Theme.of(context).textTheme.bodyText1,
),
Text(
"Hello World",
style: Theme.of(context).textTheme.headline3,
),
Switch(
value: true,
onChanged: (value) {},
),
CupertinoSwitch(
value: true,
onChanged: (value) {},
activeColor: Colors.red,
),
RaisedButton(
child: Text("R"),
onPressed: () {},
),
Card(
child: Text(
"Hello,Smile",
style: TextStyle(fontSize: 50),
),
)
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(label: '首页', icon: Icon(Icons.home)),
BottomNavigationBarItem(label: '分类', icon: Icon(Icons.category))
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (ctx) {
return SecondPage();
},
),
);
},
),
);
}
}
代码运行效果图如下:
效果图
如果某个具体的Widget不希望直接使用全局的Theme,而希望自己来定义,只需要在Widget的父节点包裹一下Theme
即可。创建另外一个新的页面,页面中使用新的主题:在新的页面的Scaffold
外,包裹了一个Theme
,并且设置data为一个新的ThemeData
,代码示例:
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(primaryColor: Colors.purple),
child: Scaffold(
appBar: AppBar(
title: Text("第二页"),
backgroundColor: Colors.purple,
),
body: Center(
child: Text("Second Page"),
),
floatingActionButton: Theme(
data: Theme.of(context).copyWith(
colorScheme:
Theme.of(context).colorScheme.copyWith(secondary: Colors.pink),
),
child: FloatingActionButton(
child: Icon(Icons.pets),
onPressed: () {},
),
),
),
);
}
}
代码运行效果图如下:
效果图
这里有一个注意事项:accentColor
在这里并不会被覆盖。需要使用:
Theme.of(context).copyWith
(
colorScheme:Theme.of(context).colorScheme.copyWith(secondary: Colors.pink),
)
网友评论