首頁 > 軟體

flutter中如何使用和擴充套件ThemeData實現詳解

2022-11-15 14:01:20

前言

做過UI開發的同學都知道,在開發中我們通常會將 文字大小、色值 等內容放在組態檔中,通過統一的管理類來讀取(嚴禁在UI程式碼中寫死)。以便後續調整時不用修改原始碼,只需要修改組態檔即可。

例如這樣:

  • 定義常數存放
/// 存放顏色常數
abstract class ColorConfigs {
  static const Color background = Color(0xFFFF6600);
  static const Color textHint = Color(0xFFA0A4A7);
}
  • 通過統一獲取
/// GOOD
Container(
  //通過 ColorConfig 獲取色值
  color: ColorConfigs.background,
)
/// BAD
Container(
  //寫死
  color: Color(0xFFFF6600),
)

Flutter為我們提供了Theme類,可以讓我們節省封裝常數設定類(如上範例中的 ColorConfigs)的步驟。將色值、字型風格等設定內容存入ThemeData中,子控制元件可統一通過 Theme.of(context)讀取 color、textStyle、等設定資訊。

本篇通過換膚demo,介紹在flutter專案中如何使用 theme 以及如何對 themeData 進行欄位擴充套件,實現全域性的主題設定管理。

Theme 的基本使用方式

1. Theme 的註冊

MaterialApp(
  theme: myThemeData, //一個ThemeData的範例,下面提供具體程式碼
  home: BodyWidget(),
)

我們做全域性的主體設定,在 MaterialApp 中對 theme 欄位進行入參賦值。範例程式碼中的 myThemeData 是一個 ThemeData 的實現範例,可通過 ThemeData 的構造方法來檢視其可供儲存的主體及樣式資訊,按照各自所需進行引數賦值。

下面是小編在自己專案中用到的ThemeData設定項,定義了各種狀態顏色、字型樣式、可供參考:

myThemeData

val myThemeData = ThemeData(
  primaryColor: Colors.white,
  disabledColor: const Color(0xffcbced0),
  backgroundColor: const Color(0xfff3f4f5),
  hintColor: const Color(0xffe2e5e7),
  errorColor: const Color(0xffe21a1a),
  highlightColor: const Color(0xffa7d500),
  shadowColor: const Color(0xffa0a4a7),
  selectedRowColor: const Color(0xfff3f4f5),
  colorScheme: const ColorScheme.light(
    primary: Colors.white,
    secondary: Color(0xffa7d500),
    background: Color(0xfff3f4f5),
    error: Color(0xffe21a1a),
    onPrimary: Color(0xff242524),
    onError: Colors.white,
    onBackground: Color(0xffe2e5e7),
    onSecondary: Color(0xff707275),
  ),
  textTheme: TextTheme(
    headline1: TextStyle(
      fontSize: 17.sp,
      fontWeight: FontWeight.bold,
      color: const Color(0xff242524),
    ),
    headline2: TextStyle(
      fontSize: 16.sp,
      fontWeight: FontWeight.bold,
      color: const Color(0xff242524),
    ),
    ...中間省略 healin3 ~ headline5,只是設定不一樣
    headline6: TextStyle(
      fontSize: 14.sp,
      fontWeight: FontWeight.bold,
      color: const Color(0xff707275),
    ),
    subtitle1: TextStyle(
      fontSize: 12.sp,
      fontWeight: FontWeight.w500,
      color: const Color(0xff242524),
    ),
    subtitle2: TextStyle(
      fontSize: 12.sp,
      fontWeight: FontWeight.w500,
      color: const Color(0xff707275),
    ),
    bodyText1: TextStyle(
      fontSize: 11.sp,
      fontWeight: FontWeight.normal,
      color: const Color(0xff242524),
    ),
    bodyText2: TextStyle(
      fontSize: 11.sp,
      fontWeight: FontWeight.normal,
      color: const Color(0xff242524),
    ),
  ),
)

2. 讀取 ThemeData 裡的設定:

@override
Widget build(BuildContext context) {
  return Container(
    color: Theme.of(context).backgroundColor,
    child: Text(
        'hellow', 
        style: Theme.of(context).headline).bodyText1,
  );
}
  • Theme.of(context).backgroundColor:讀取主題設定中的背景顏色,在 myThemeData 中進行過賦值操作
  • Theme.of(context).headline).bodyText1:讀取主題設定中鍵值為 bodyText1 的字型樣式

小技巧介紹

通常為了便於開發閱讀,我們也可以使用extension對 ThemeData 內屬性進行重新命名獲取:

新建 extension_theme.dart,檔案名字隨意:

///用於重新命名顏色屬性
extension ThemeDataColorExtension on ThemeData {
  Color get bgColor => colorScheme.onBackground;
 ...
}
///用於重新命名字型樣式屬性
extension ThemeDataTextStyleExtension on ThemeData {
  TextStyle get bodyStyle => textTheme.bodyText1!;
 ...
}

在UI頁面進行參照匯入使用,上面的 demo 可改為:

import ./extension_theme.dart
...
@override
Widget build(BuildContext context) {
  return Container(
    color: Theme.of(context).bgColor,
    child: Text(
        'hellow', 
        style: Theme.of(context).bodyStyle,
  );
}

ThemeData 內建欄位不夠用,如何擴充套件?

從 ThemeData 的建構函式中我們可以看到,ThemeData 內建的欄位是有限的。假如我們的UI設計包含的色值數量或者字型樣式數量超出了 ThemeData 可供設定數量怎麼辦呢?

比如:我們想新增一個色值設定,名字就叫 connerColor,我們還想保持統一,一律通過 ThemeData 來統一讀取統一設定,要如何處理呢?

小編在專案裡是這麼做的,將 ThemeData 進行一層封裝,以新增 connerColor 為例,具體程式碼結合下面


IT145.com E-mail:sddin#qq.com