Theme 類將主題應用於子控件,Theme(主題)它描述了應用程序的顏色和排版選擇。Theme有兩種:全局Theme和局部Theme。全局Theme是由應用程序根MaterialApp建立的Theme;而局部Theme是在應用程序某個區域範圍中用於覆蓋全局主題。html
Google官網介紹:api.flutter.dev/flutter/mat…android
Theme({Key key,
@required ThemeData data,
bool isMaterialAppTheme: false,
@required Widget child })
複製代碼
Object -> Diagnosticable -> DiagnosticableTree -> Widget -> StatelessWidget -> Theme。git
從Theme的構造函數咱們不難看出,Flutter 中是經過ThemeData去保存共享應用的主題及樣式等信息的,所以咱們繼續翻一下官方文檔,研究研究一下ThemeData包含了哪些知識點。github
繼承關係: Object -> Diagnosticable -> ThemeDatacanvas
構造函數:api
ThemeData({Brightness brightness,
MaterialColor primarySwatch,
Color primaryColor,
Brightness primaryColorBrightness,
Color primaryColorLight,
Color primaryColorDark,
Color accentColor,
Brightness accentColorBrightness,
Color canvasColor,
Color scaffoldBackgroundColor,
Color bottomAppBarColor,
Color cardColor,
Color dividerColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
InteractiveInkFeatureFactory splashFactory,
Color selectedRowColor,
Color unselectedWidgetColor,
Color disabledColor,
Color buttonColor,
ButtonThemeData buttonTheme,
Color secondaryHeaderColor,
Color textSelectionColor,
Color cursorColor,
Color textSelectionHandleColor,
Color backgroundColor,
Color dialogBackgroundColor,
Color indicatorColor,
Color hintColor,
Color errorColor,
Color toggleableActiveColor,
String fontFamily,
TextTheme textTheme,
TextTheme primaryTextTheme,
TextTheme accentTextTheme,
InputDecorationTheme inputDecorationTheme,
IconThemeData iconTheme,
IconThemeData primaryIconTheme,
IconThemeData accentIconTheme,
SliderThemeData sliderTheme,
TabBarTheme tabBarTheme,
CardTheme cardTheme,
ChipThemeData chipTheme,
TargetPlatform platform,
MaterialTapTargetSize materialTapTargetSize,
PageTransitionsTheme pageTransitionsTheme,
AppBarTheme appBarTheme,
BottomAppBarTheme bottomAppBarTheme,
ColorScheme colorScheme,
DialogTheme dialogTheme,
FloatingActionButtonThemeData floatingActionButtonTheme,
Typography typography,
CupertinoThemeData cupertinoOverrideTheme,
SnackBarThemeData snackBarTheme,
BottomSheetThemeData bottomSheetTheme })
複製代碼
從其構造函數不難看出,它主要保存了各類顏色及字體、Icon樣式等設置。因爲屬性過多,咱們挑一些經常使用的講一講:數組
brightness - Brightness類型,應用程序的總體主題亮度。用於按鈕等小部件,以肯定在不使用主色(primaryColor)或強調色(accentColor)時選擇什麼顏色。當亮度較暗時,畫布、卡片和原色都較暗。當亮度爲光時,畫布和卡片的顏色是明亮的,原色的暗度根據原色亮度變化。當亮度較暗時,原色(primaryColor)與卡片和畫布顏色的對比度較差;當亮度較暗時,用白色或亮藍色來對比。bash
primarySwatch - MaterialColor 類型,Material 主題中定義一種顏色,它具備十種顏色陰影的顏色樣本。值越大顏色越深,10個有效的index分別爲:50,100,200,…,900。默認是取中間值500。app
primaryColor - Color類型,App主要部分的背景色(ToolBar,Tabbar等)less
primaryColorBrightness - Brightness類型,primaryColor的亮度,用於肯定設置在primaryColor上部的文本和圖標顏色(如:工具欄文本(toolbar text))。
primaryColorLight - Color類型,primaryColor的較淺版本
primaryColorDark - Color類型,primaryColor的較深版本
accentColor - Color類型,前景色(按鈕、文本、覆蓋邊緣效果等)
accentColorBrightness - Brightness類型,accentColor的亮度。用於肯定位於accentColor上部的文本和圖標顏色(例如,浮動操做按鈕(FloatingButton)上的圖標)
canvasColor - Color類型,MaterialType.canvas Material的默認顏色。
scaffoldBackgroundColor - Color類型,做爲Scaffold下的Material默認顏色,用於materia應用程序或app內頁面的背景色。
bottomAppBarColor - Color類型,bottomAppBarColor的默認顏色。這能夠經過指定BottomAppBar.color來覆蓋。
cardColor - Color類型,用在卡片(Card)上的Material的顏色。
dividerColor - Color類型,分隔符(Dividers)和彈窗分隔符(PopupMenuDividers)的顏色,也用於ListTiles和DataTables的行之間。要建立使用這種顏色的合適的邊界,請考慮Divider.createBorderSide。
highlightColor - Color類型,用於墨水噴濺動畫或指示菜單被選中時的高亮顏色
splashColor - Color類型,墨水濺出的顏色
splashFactory - InteractiveInkFeatureFactory類型,定義InkWall和InkResponse產成的墨水噴濺時的外觀。
selectedRowColor - Color類型,用於高亮選定行的顏色。
unselectedWidgetColor - Color類型,小部件處於非活動(但啓用)狀態時使用的顏色。例如,未選中的複選框。一般與accentColor造成對比。
disabledColor - Color類型,無效的部件(widget)的顏色,無論它們的狀態如何。例如,一個禁用的複選框(能夠選中或不選中)。
buttonColor - Color類型,Material中RaisedButtons使用的默認填充色。
buttonTheme - ButtonThemeData類型,定義按鈕小部件的默認配置,如RaisedButton和FlatButton。
secondaryHeaderColor - Color類型,有選定行時PaginatedDataTable標題的顏色
textSelectionColor - Color類型,文本字段(如TextField)中文本被選中的顏色。
cursorColor - Color類型,在 Material-style 文本字段(如TextField)中光標的顏色。
textSelectionHandleColor - Color類型,用於調整當前選定文本部分的句柄的顏色。
backgroundColor - Color類型,與primaryColor對比的顏色(例如 用做進度條的剩餘部分)。
dialogBackgroundColor - Color類型,Color類型,Dialog元素的背景色
indicatorColor - Color類型,TabBar中選項選中的指示器顏色。
hintColor - Color類型,用於提示文本或佔位符文本的顏色,例如在TextField中。
errorColor - Color類型,用於輸入驗證錯誤的顏色,例如在TextField中。
toggleableActiveColor - Color類型,用於突出顯示切換Widget(如Switch,Radio和Checkbox)的活動狀態的顏色。
fontFamily - String類型,字體類型
textTheme - TextTheme類型,與卡片和畫布對比的文本顏色
primaryTextTheme - TextTheme類型,與primary color造成對比的文本主題。
accentTextTheme - TextTheme類型,與accent color造成對比的文本主題。
inputDecorationTheme - InputDecorationTheme類型,InputDecorator、TextField和TextFormField的默認InputDecoration值基於此主題。
iconTheme - IconThemeData類型,與卡片和畫布顏色造成對比的圖標主題。
primaryIconTheme - IconThemeData類型,與原色(primary color)造成對比的圖標主題。
accentIconTheme - IconThemeData類型,與前景色(accent color)造成對比的圖標主題。
sliderTheme - SliderThemeData類型,SliderThemeData類型,用於渲染Slider的顏色和形狀。
tabBarTheme - TabBarTheme類型, 一個主題,用於自定義選項卡欄指示器的尺寸、形狀和顏色。
chipTheme - ChipThemeData類型,用於Chip的顏色和樣式
platform - TargetPlatform類型,widget應該適應目標的平臺。
materialTapTargetSize - MaterialTapTargetSize類型,配置特定材料部件的hit測試大小。
pageTransitionsTheme - PageTransitionsTheme類型,每一個目標平臺的默認MaterialPageRoute轉換。
colorScheme ColorScheme類型,一組13種顏色,可用於配置大多數組件的顏色屬性。
typography - Typography類型,用於配置TextTheme、primaryTextTheme和accentTextTheme的顏色和幾何文本主題值。
它是一個 static 方法。子控件經過使用Theme.of來獲取當前主題的ThemeData對象,當控件使用Theme.of時,若是主題稍後更改,則會自動重建以即可以應用更改。咱們能夠經過Theme.of查看當前應用程序的配色方案。
ThemeData.of 方法代碼:
ThemeData of (
BuildContext context, {
bool shadowThemeOnly: false
})
複製代碼
ThemeData數據來自最近的給定上下文的Theme實例。若是給定的 context 包含在提供MaterialLocalizations的Localizations部件中,則返回的數據將根據最近的可用MaterialLocalizations進行本地化。若是給定的構建上下文中沒有主題,則默認爲新的ThemeData.fallback。
示例用法以下:
@override
Widget build(BuildContext context) {
return Text(
'Theme Example',
style: Theme.of(context).textTheme.title,
);
}
複製代碼
到這裏咱們已經知道如何去設置flutter主題了,在flutter中,主題又分全局主題和局部主題。接下來咱們講解一下這兩種方式的適用場景及區別。
在建立應用全局主題時,咱們提供一個ThemeData對象給MaterialApp便可,若是構造函數沒有設置ThemeData,則Flutter會建立一個默認的主題。下面咱們實踐一下,寫個自定義全局主題的簡單示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.light, //指定亮度主題,有白色/黑色兩種可選。
primaryColor: Colors.blue[800], //這裏咱們選藍色爲基準色值。
accentColor: Colors.lightBlue[100]), //這裏咱們選淺藍色爲強調色值。
home: ThemeTest(),
);
}
}
class ThemeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ThemeTest"), //頁面標題
),
body: Container(
color: Theme.of(context).primaryColor, //內容背景顏色
margin: EdgeInsets.all(100.0),
padding: EdgeInsets.all(10.0),
child: Text(
"MaterialApp Theme Color", //內容文本
style: TextStyle(
fontSize: 20, color: Theme.of(context).accentColor), //內容文本顏色,引用的是accentColor。
textAlign: TextAlign.center,
),
),
);
}
}
複製代碼
效果圖以下:
局部主題是在應用程序某些區域中,用於覆蓋全局主題。咱們定義好一個主題後,就能夠在Widget的build方法中經過Theme.of(context)方法來使用它。Theme.of(context)將查找Widget樹並返回樹中最近的Theme。若是Widget之上有一個單獨的局部Theme定義,則返回該主題的值;若是不是,則返回App全局主題。咱們講一下主要的幾種建立方法:
經過從新建立Theme的方式,建立一個實例, 並從新建立ThemeData,賦值給data。而後指定child Widget,將ThemeData傳遞給Theme Widget,代碼以下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.light, //指定亮度主題,有白色/黑色兩種可選。
primaryColor: Colors.blue[800], //這裏咱們選藍色爲基準色值。
accentColor: Colors.lightBlue[100]), //這裏咱們選淺藍色爲強調色值。
home: Theme(
data: ThemeData(accentColor: Colors.yellow),
child: ThemeTest())); //建立局部主題,將accentColor設置爲黃色
}
}
class ThemeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ThemeTest"),
),
body: Container(
color: Theme.of(context).primaryColor,
margin: EdgeInsets.all(100.0),
padding: EdgeInsets.all(10.0),
child: Text(
"MaterialApp Theme Color",
style: TextStyle(
fontSize: 20, color: Theme.of(context).accentColor), //應用局部主題顏色
textAlign: TextAlign.center,
)),
);
}
}
複製代碼
效果圖以下:
這裏有個小坑點須要注意,咱們須要在Widget的父層Widget去設置局部Theme,纔會生效;若是咱們直接在局部Theme的child 屬性指定的Widget中去使用的話,會拿到系統的全局Theme.
以下示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.light, //指定亮度主題,有白色/黑色兩種可選。
primaryColor: Colors.blue[800], //這裏咱們選藍色爲基準色值。
accentColor: Colors.white), //設置爲白色。
home: ThemeTest(),
);
}
}
class ThemeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ThemeTest"),//頁面標題
),
body: Container(
color: Theme.of(context).primaryColor,
margin: EdgeInsets.all(100.0),
padding: EdgeInsets.all(10.0),
child: Theme(
data: ThemeData(accentColor: Colors.red), //設置紅色
//建立accentColor 爲綠色的局部主題,若局部主題Theme 的Child 是 Text,則Text引用局部主題色不會生效,拿到的仍是局部Themes上層的值,即全局主題的值。
child: Text(
"MaterialApp Theme Color",
style: TextStyle(
fontSize: 20, color: Theme.of(context).accentColor), //應用主題色
textAlign: TextAlign.center,
))),
);
}
}
複製代碼
效果圖以下:
能夠從截圖看到,Text顯示的顏色依舊是白色,並未變成咱們所指望的紅色,所以咱們使用的時候須要額外注意這點。
除了 建立Theme 對象的方式去使用局部主題,咱們能夠經過使用copyWith方法來實現,這樣的話,咱們去修改父主題時,無需覆蓋全部的主題屬性,只須要將咱們想改動的屬性指定便可。
將原先的:
data: ThemeData(accentColor: Colors.yellow)
複製代碼
改爲:
Theme.of(context).copyWith(accentColor: Colors.yellow)
複製代碼
這樣一來,咱們的局部主題除了accentColor改爲了指定值,其餘屬性依然可使用它上一層 Theme的屬性值,而不是變成系統默認的。
除了上述兩種方法以外,咱們還能夠根據設備的平臺類型(iOS,Android和Fuchsia)去提供不一樣的主題:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final ThemeData iOSTheme = ThemeData(
brightness: Brightness.light,
primaryColor: Colors.grey[600],
accentColor: Colors.white,
);
final ThemeData androidTheme = ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.yellow[300],
accentColor: Colors.deepPurple[800],
);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.grey[100],
accentColor: Colors.white,
),
home: Theme(
data: defaultTargetPlatform == TargetPlatform.android
? androidTheme
: iOSTheme,
child: ThemeTest()),
);
}
}
class ThemeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ThemeTest"),
),
body: Container(
color: Theme.of(context).primaryColor,
margin: EdgeInsets.all(100.0),
padding: EdgeInsets.all(10.0),
child: Text(
"MaterialApp Theme Color",
style:
TextStyle(fontSize: 20, color: Theme.of(context).accentColor),
textAlign: TextAlign.center,
)),
);
}
}
複製代碼
Android 端效果圖:
iOS 端效果圖:
本篇文章主要講述了Theme 的一些經常使用方法及屬性。同時對全局主題、局部主題、不一樣平臺主題的設置方法也作了較詳細的實踐示例。flutter 中對主題的設置相對而言比較靈活,你們能夠多多實踐操做一波。
xiaosongzeem |