Flutter Theme應用主題共享顏色和字型樣式

藍色微笑ing發表於2019-12-10

前言

一般情況下,我們的Application都有獨特的特點,UI設計師會結合業務和品牌的特點,指定元件的視覺定製。包含主題色,圓角,邊框等各種樣式定製。

我們就需要使用 Theme 在應用程式中定製全域性顏色和各種樣式。

當我們不設定主題時,系統會生成預設主題。比如我們最熟悉的primaryColor,預設顏色是Colors.blue,Brightness預設值Brightness.light.

官方關於主題的介紹請點選 使用主題共享顏色和字型樣式

設定主題的兩種方式

方式一:全域性設定

全域性設定主題就是在應用程式根MaterialApp定製ThemeData.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Theme',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}
複製程式碼

方式二:區域性設定

我們想要在某些特定的頁面,定製不一樣的主題,可以區域性設定Theme. 具體有兩種方式,分別是建立特有的ThemeData擴充套件父主題

建立特有的ThemeData(直接覆蓋父主題)

如果我們不想使用當初定製應用程式的主題,使用這種方式,可以直接覆蓋原有的父主題。

提示,Theme是一個Widget,繼承了StatelessWidget.

Theme(
  data: ThemeData(
    accentColor: Colors.yellow,
  ),
  child: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
  ),
);
複製程式碼

擴充套件父主題

我們只需要改變ThemeData的某一項,可以使用 copyWith 擴充套件負主題。

Theme(
  data: Theme.of(context).copyWith(accentColor: Colors.yellow),
  child: FloatingActionButton(
    onPressed: null,
    child: Icon(Icons.add),
  ),
);
複製程式碼

獲取已設定的主題

通過Theme.of(context)函式獲取已設定的主題。

比如獲取primaryColor

Color primaryColor = Theme.of(context).primaryColor;
複製程式碼

ThemeData的主要屬性及預設值

提示:文字太長,如需查詢,使用 ctrl + f.

屬性 型別 描述
brightness Brightness 有兩種可以選擇,Brightness.light和Brightness.dark
primarySwatch MaterialColor MaterialColor間接繼承了Color
primaryColor Color 主題色
primaryColorBrightness Brightness 判斷primaryColor是Brightness.light,還是Brightness.dark
primaryColorLight Color primaryColor的較暗顏色
primaryColorDark Color primaryColor的較亮顏色
accentColor Color 文字、按鈕等前景色
accentColorBrightness Brightness accentColor的亮度,用於確定放置在突出顏色頂部的文字和圖示的顏色(例如FloatingButton上的圖示)
canvasColor Color MaterialType.canvas Material的預設顏色
scaffoldBackgroundColor Color Material預設顏色
bottomAppBarColor Color BottomAppBar的預設顏色
cardColor Color Material被用作Card時的顏色
dividerColor Color Dividers和PopupMenuDividers的顏色,也用於ListTiles中間,和DataTables的每行中間
focusColor Color
hoverColor Color
highlightColor Color 用於類似墨水噴濺動畫或指示選單被選中的高亮顏色
splashColor Color 墨水噴濺的顏色
splashFactory InteractiveInkFeatureFactory 定義InkWall和InkResponse生成的墨水噴濺的外觀
selectedRowColor Color 選中行時的高亮顏色
unselectedWidgetColor Color 用於Widget處於非活動(但已啟用)狀態的顏色。 例如,未選中的核取方塊。 通常與accentColor形成對比
disabledColor Color 用於Widget無效的顏色,無論任何狀態。例如禁用核取方塊。
buttonColor Color Material中RaisedButtons使用的預設填充色。
buttonTheme ButtonThemeData 定義了按鈕等控制元件的預設配置,像RaisedButton和FlatButton
toggleButtonsTheme ToggleButtonsThemeData 定義ToggleButtons控制元件的預設配置
secondaryHeaderColor Color 有選定行時PaginatedDataTable標題的顏色。
textSelectionColor Color 文字欄位中選中文字的顏色,例如TextField。
cursorColor Color 游標顏色
textSelectionHandleColor Color 用於調整當前文字的哪個部分的控制程式碼顏色。
backgroundColor Color 作為Scaffold基礎的Material預設顏色,典型Material應用或應用內頁面的背景顏色。
dialogBackgroundColor Color Dialog元素的背景色。
indicatorColor Color TabBar中選項選中的指示器顏色。
hintColor Color 用於提示文字或佔位符文字的顏色,例如在TextField中。
errorColor Color 用於輸入驗證錯誤的顏色,例如在TextField中。
toggleableActiveColor Color 用於突出顯示切換Widget(如Switch,Radio和Checkbox)的活動狀態的顏色。
fontFamily String 字型系列,如“Roboto”
textTheme TextTheme 文字預設主題
primaryTextTheme TextTheme 一個與主色對比的文字主題
accentTextTheme TextTheme 與突出顏色對照的文字主題。
inputDecorationTheme InputDecorationTheme InputDecorator,TextField和TextFormField的預設InputDecoration值基於此主題。
iconTheme IconThemeData 與卡片和畫布顏色形成對比的圖示主題。
primaryIconTheme IconThemeData 一個與主色對比的圖片主題。
accentIconTheme IconThemeData 與突出顏色對照的圖片主題。
sliderTheme SliderThemeData 用於渲染Slider的顏色和形狀。
tabBarTheme TabBarTheme TabBar的預設出題
tooltipTheme TooltipThemeData 提示Tooltip的預設主題
cardTheme CardTheme Card的預設主題
chipTheme ChipThemeData 用於渲染Chip的顏色和樣式。
platform TargetPlatform Widget需要適配的目標型別。
materialTapTargetSize MaterialTapTargetSize
applyElevationOverlayColor bool
pageTransitionsTheme PageTransitionsTheme
appBarTheme AppBarTheme AppBar預設主題
bottomAppBarTheme BottomAppBarTheme BottomAppBar的預設主題
colorScheme ColorScheme
dialogTheme DialogTheme Dialog的預設主題
floatingActionButtonTheme FloatingActionButtonThemeData FloatingActionButton的預設主題
typography Typography
cupertinoOverrideTheme CupertinoThemeData
snackBarTheme SnackBarThemeData SnackBar的預設主題
bottomSheetTheme BottomSheetThemeData
popupMenuTheme PopupMenuThemeData
bannerTheme MaterialBannerThemeData
dividerTheme DividerThemeData

ThemeData構造器原始碼

看原始碼更容易理解

brightness ??= Brightness.light;
final bool isDark = brightness == Brightness.dark;
primarySwatch ??= Colors.blue;
primaryColor ??= isDark ? Colors.grey[900] : primarySwatch;
primaryColorBrightness ??= estimateBrightnessForColor(primaryColor);
primaryColorLight ??= isDark ? Colors.grey[500] : primarySwatch[100];
primaryColorDark ??= isDark ? Colors.black : primarySwatch[700];
final bool primaryIsDark = primaryColorBrightness == Brightness.dark;
toggleableActiveColor ??= isDark ? Colors.tealAccent[200] : (accentColor ?? primarySwatch[600]);
accentColor ??= isDark ? Colors.tealAccent[200] : primarySwatch[500];
accentColorBrightness ??= estimateBrightnessForColor(accentColor);
final bool accentIsDark = accentColorBrightness == Brightness.dark;
canvasColor ??= isDark ? Colors.grey[850] : Colors.grey[50];
scaffoldBackgroundColor ??= canvasColor;
bottomAppBarColor ??= isDark ? Colors.grey[800] : Colors.white;
cardColor ??= isDark ? Colors.grey[800] : Colors.white;
dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000);

// Create a ColorScheme that is backwards compatible as possible
// with the existing default ThemeData color values.
colorScheme ??= ColorScheme.fromSwatch(
  primarySwatch: primarySwatch,
  primaryColorDark: primaryColorDark,
  accentColor: accentColor,
  cardColor: cardColor,
  backgroundColor: backgroundColor,
  errorColor: errorColor,
  brightness: brightness,
);

splashFactory ??= InkSplash.splashFactory;
selectedRowColor ??= Colors.grey[100];
unselectedWidgetColor ??= isDark ? Colors.white70 : Colors.black54;
// Spec does not specify a dark theme secondaryHeaderColor, this is a guess.
secondaryHeaderColor ??= isDark ? Colors.grey[700] : primarySwatch[50];
textSelectionColor ??= isDark ? accentColor : primarySwatch[200];
// TODO(sandrasandeep): change to color provided by Material Design team
cursorColor = cursorColor ?? const Color.fromRGBO(66, 133, 244, 1.0);
textSelectionHandleColor ??= isDark ? Colors.tealAccent[400] : primarySwatch[300];
backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
dialogBackgroundColor ??= isDark ? Colors.grey[800] : Colors.white;
indicatorColor ??= accentColor == primaryColor ? Colors.white : accentColor;
hintColor ??= isDark ? const Color(0x80FFFFFF) : const Color(0x8A000000);
errorColor ??= Colors.red[700];
inputDecorationTheme ??= const InputDecorationTheme();
pageTransitionsTheme ??= const PageTransitionsTheme();
primaryIconTheme ??= primaryIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
accentIconTheme ??= accentIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
iconTheme ??= isDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black87);
platform ??= defaultTargetPlatform;
typography ??= Typography(platform: platform);
final TextTheme defaultTextTheme = isDark ? typography.white : typography.black;
textTheme = defaultTextTheme.merge(textTheme);
final TextTheme defaultPrimaryTextTheme = primaryIsDark ? typography.white : typography.black;
primaryTextTheme = defaultPrimaryTextTheme.merge(primaryTextTheme);
final TextTheme defaultAccentTextTheme = accentIsDark ? typography.white : typography.black;
accentTextTheme = defaultAccentTextTheme.merge(accentTextTheme);
materialTapTargetSize ??= MaterialTapTargetSize.padded;
applyElevationOverlayColor ??= false;
if (fontFamily != null) {
  textTheme = textTheme.apply(fontFamily: fontFamily);
  primaryTextTheme = primaryTextTheme.apply(fontFamily: fontFamily);
  accentTextTheme = accentTextTheme.apply(fontFamily: fontFamily);
}

// Used as the default color (fill color) for RaisedButtons. Computing the
// default for ButtonThemeData for the sake of backwards compatibility.
buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
focusColor ??= isDark ? Colors.white.withOpacity(0.12) : Colors.black.withOpacity(0.12);
hoverColor ??= isDark ? Colors.white.withOpacity(0.04) : Colors.black.withOpacity(0.04);
buttonTheme ??= ButtonThemeData(
  colorScheme: colorScheme,
  buttonColor: buttonColor,
  disabledColor: disabledColor,
  focusColor: focusColor,
  hoverColor: hoverColor,
  highlightColor: highlightColor,
  splashColor: splashColor,
  materialTapTargetSize: materialTapTargetSize,
);
toggleButtonsTheme ??= const ToggleButtonsThemeData();
disabledColor ??= isDark ? Colors.white38 : Colors.black38;
highlightColor ??= isDark ? _kDarkThemeHighlightColor : _kLightThemeHighlightColor;
splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor;

sliderTheme ??= const SliderThemeData();
tabBarTheme ??= const TabBarTheme();
tooltipTheme ??= const TooltipThemeData();
appBarTheme ??= const AppBarTheme();
bottomAppBarTheme ??= const BottomAppBarTheme();
cardTheme ??= const CardTheme();
chipTheme ??= ChipThemeData.fromDefaults(
  secondaryColor: primaryColor,
  brightness: brightness,
  labelStyle: textTheme.body2,
);
dialogTheme ??= const DialogTheme();
floatingActionButtonTheme ??= const FloatingActionButtonThemeData();
cupertinoOverrideTheme = cupertinoOverrideTheme?.noDefault();
snackBarTheme ??= const SnackBarThemeData();
bottomSheetTheme ??= const BottomSheetThemeData();
popupMenuTheme ??= const PopupMenuThemeData();
bannerTheme ??= const MaterialBannerThemeData();
dividerTheme ??= const DividerThemeData();
複製程式碼

相關文章