Flutter深色模式適配的實(shí)現(xiàn)
一、簡(jiǎn)介
Flutter的深色模式以及跟隨系統(tǒng)設(shè)置比較簡(jiǎn)單,我感覺(jué)需要注意的是開(kāi)發(fā)過(guò)程中盡量使用Theme中的顏色與樣式,開(kāi)發(fā)過(guò)程中遇到的比較大的坑就是provider的一些問(wèn)題,可能是因?yàn)槲矣玫陌姹拘乱恍?,網(wǎng)上找了很多文章,總會(huì)遇到一些問(wèn)題。本文的深色模式適配是通過(guò)修改themeMode來(lái)實(shí)現(xiàn)的,供諸位有緣人參考。
二、環(huán)境介紹
1. Flutter: 2.0.3
2. Dart: 2.12.0
3. provider: 5.0.0
狀態(tài)管理,用于運(yùn)行時(shí)切換主題
4. shared_preferences: 2.0.5
數(shù)據(jù)持久化,用于保存當(dāng)前選中的主題,以便下次啟動(dòng)時(shí)讀取使用用戶選擇的主題
environment: sdk: ">=2.12.0 <3.0.0" dependencies: flutter: sdk: flutter # 忽略了一些依賴... # shared_preferences https://pub.flutter-io.cn/packages/shared_preferences shared_preferences: ^2.0.5 # 全局狀態(tài)管理 https://github.com/rrousselGit/provider/blob/master/resources/translations/zh-CN/README.md provider: ^5.0.0
三、主題
1. ThemeData
factory ThemeData({ Brightness brightness, // 應(yīng)用主題亮度,可選(dark、light) VisualDensity visualDensity, // 視覺(jué)密度 MaterialColor primarySwatch, // 主要樣式,設(shè)置primaryColor后該背景色會(huì)被覆蓋 Color primaryColor, // 主要部分背景顏色(導(dǎo)航和tabBar等) Brightness primaryColorBrightness, // primaryColor的亮度 Color primaryColorLight, // primaryColor的淺色版 Color primaryColorDark, // primaryColor的深色版 Color accentColor, // 前景色(文本,按鈕等) Brightness accentColorBrightness, // accentColor的亮度 Color canvasColor, // MaterialType.canvas 的默認(rèn)顏色 Color shadowColor, // 陰影顏色 Color scaffoldBackgroundColor, // Scaffold的背景顏色。典型Material應(yīng)用程序或應(yīng)用程序內(nèi)頁(yè)面的背景顏色 Color bottomAppBarColor, // BottomAppBar的默認(rèn)顏色 Color cardColor, // Card的顏色 Color dividerColor, // Divider和PopupMenuDivider的顏色,也用于ListTile之間、DataTable的行之間等。 Color focusColor, // 突出顏色 Color hoverColor, // hoverColor Color highlightColor, // 高亮顏色,選中在潑墨動(dòng)畫(huà)期間使用的突出顯示顏色,或用于指示菜單中的項(xiàng)。 Color splashColor, // 墨水飛濺的顏色。InkWell InteractiveInkFeatureFactory splashFactory, // 定義由InkWell和InkResponse反應(yīng)產(chǎn)生的墨濺的外觀。 Color selectedRowColor, // 用于突出顯示選定行的顏色。 Color unselectedWidgetColor, // 用于處于非活動(dòng)(但已啟用)狀態(tài)的小部件的顏色。例如,未選中的復(fù)選框。通常與accentColor形成對(duì)比。也看到disabledColor。 Color disabledColor, // 禁用狀態(tài)下部件的顏色,無(wú)論其當(dāng)前狀態(tài)如何。例如,一個(gè)禁用的復(fù)選框(可以選中或未選中)。 Color buttonColor, // RaisedButton按鈕中使用的Material 的默認(rèn)填充顏色。 ButtonThemeData buttonTheme, // 定義按鈕部件的默認(rèn)配置, ToggleButtonsThemeData toggleButtonsTheme, // 切換按鈕的主題 Color secondaryHeaderColor, // 選定行時(shí)PaginatedDataTable標(biāo)題的顏色。 Color textSelectionColor, // 文本框中文本選擇的顏色,如TextField Color cursorColor, // 文本框中光標(biāo)的顏色,如TextField Color textSelectionHandleColor, // 調(diào)整當(dāng)前選定的文本部分的句柄的顏色。 Color backgroundColor, // 與主色形成對(duì)比的顏色,例如用作進(jìn)度條的剩余部分。 Color dialogBackgroundColor, // Dialog元素的背景顏色 Color indicatorColor, // 選項(xiàng)卡中選定的選項(xiàng)卡指示器的顏色。 Color hintColor, // 用于提示文本或占位符文本的顏色,例如在TextField中。 Color errorColor, // 用于輸入驗(yàn)證錯(cuò)誤的顏色,例如在TextField中 Color toggleableActiveColor, // 用于突出顯示Switch、Radio和Checkbox等可切換小部件的活動(dòng)狀態(tài)的顏色。 String fontFamily, // 文本字體 TextTheme textTheme, // 文本的顏色與卡片和畫(huà)布的顏色形成對(duì)比。 TextTheme primaryTextTheme, // 與primaryColor形成對(duì)比的文本主題 TextTheme accentTextTheme, // 與accentColor形成對(duì)比的文本主題。 InputDecorationTheme inputDecorationTheme, // 基于這個(gè)主題的 InputDecorator、TextField和TextFormField的默認(rèn)InputDecoration值。 TabBarTheme tabBarTheme, // 用于自定義選項(xiàng)卡欄指示器的大小、形狀和顏色的主題。 TooltipThemeData tooltipTheme, // tooltip主題 CardTheme cardTheme, // Card的顏色和樣式 AppBarTheme appBarTheme, // appBar主題 ColorScheme colorScheme, // 擁有13種顏色,可用于配置大多數(shù)組件的顏色。 NavigationRailThemeData navigationRailTheme, // 導(dǎo)航邊欄主題 // ... })
2. main.dart or MaterialApp
theme為默認(rèn)主題,darkTheme為深色主題,themeMode為當(dāng)前使用哪個(gè)主題,可選值system、light、dark,只有在th``eme與darkTheme都設(shè)置的時(shí)候才會(huì)生效,我們的theme與darkTheme都直接使用ThemeData對(duì)象,給他指定了brightness,而不是使用這樣感覺(jué)可以方便修改樣式,當(dāng)然也可以抽出來(lái)封裝一下,我這沒(méi)有去處理。
MaterialApp( theme: ThemeData( brightness: Brightness.light, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), darkTheme: ThemeData( brightness: Brightness.dark, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), themeMode: context.watch<ThemeModel>().theme );
四、全局配置
全局配置是在MaterialApp加載之前進(jìn)行一寫(xiě)初始化操作,參考了《Flutter實(shí)戰(zhàn)》電子書(shū),F(xiàn)lutter當(dāng)中SharedPreferences是異步初始化,還有Dio網(wǎng)絡(luò)請(qǐng)求的緩存也需要提前初始化,我們這里SharedPreferences加載完之后在進(jìn)行之后的操作,SpUtils中的SharedPreferences使用的Global全局配置中的靜態(tài)屬性。
1. Global
class Global { static late SharedPreferences prefs; static ThemeMode theme = ThemeMode.light; // 是否為release版 static bool get isRelease => bool.fromEnvironment("dart.vm.product"); //初始化全局信息,會(huì)在APP啟動(dòng)時(shí)執(zhí)行 static Future init() async { WidgetsFlutterBinding.ensureInitialized(); prefs = await SharedPreferences.getInstance(); // 當(dāng)前本地存儲(chǔ)的主題 String themeValue = await SpUtils.instance.getStorage(SpConstants.skin); theme = themeStringToThemeMode(themeValue); //初始化網(wǎng)絡(luò)請(qǐng)求相關(guān)配置 HttpManager(); } }
2. main.dart
// Global加載完成后掉用runApp Global.init().then((e) => runApp());
3. themeStringToThemeMode()
字符串轉(zhuǎn)ThemeMode
ThemeMode themeStringToThemeMode(String themeValue){ ThemeMode theme = ThemeMode.light; switch (themeValue) { case "light": theme = ThemeMode.light; break; case "dark": theme = ThemeMode.dark; break; case "system": theme = ThemeMode.system; break; } return theme; }
五、使用狀態(tài)管理(provider)切換主題
> 此處大坑,處處勸退,感謝Flutter provider勸退經(jīng)歷這篇文章
1. 構(gòu)建主題Model
class ThemeModel extends ChangeNotifier { // 獲取當(dāng)前主題,如果為設(shè)置主題,則默認(rèn)使用淺色模式 ThemeMode get theme => Global.theme; // 主題改變后,通知其依賴項(xiàng),新主題會(huì)立即生效 set theme(ThemeMode themeMode) { if (themeMode != theme) { Global.theme = themeMode; notifyListeners(); } } }
2. main.dart(監(jiān)聽(tīng)值變化)
此處為main.dart文件的完整代碼,下面有關(guān)provider的一些使用方式可能與網(wǎng)上很多文章不一樣的,但是這都是官網(wǎng)文檔的最新推薦使用方式。讀取當(dāng)前provider中存儲(chǔ)的主題context.watch<ThemeModel>().theme
void main() { //頂部狀態(tài)欄透明 SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle(statusBarColor: Colors.transparent)); Global.init().then((e) => runApp( MultiProvider( providers: [ListenableProvider<ThemeModel>(create: (_) => ThemeModel())], builder: (context, child) { return WanAndroid(); }), )); } class WanAndroid extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( initialRoute: '/', theme: ThemeData( brightness: Brightness.light, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), darkTheme: ThemeData( brightness: Brightness.dark, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), themeMode: context.watch<ThemeModel>().theme, routes: { '/': (context) => SplashPage(), '/index': (context) => IndexPage(), '/login': (context) => LoginPage(), '/setting': (context) => SettingPage(), }, title: '玩Android-Flutter版', ); } }
3. 切換主題
修改provider中保存的值即可。
// themeStringToThemeMode方法代碼在上面有寫(xiě) context.read<ThemeModel>().theme = themeStringToThemeMode(value);
六、源碼
- 源碼:github.com/sdwfqin/flutter_wanandroid
到此這篇關(guān)于Flutter深色模式適配的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Flutter深色模式適配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android自定義控件和自定義回調(diào)函數(shù)步驟示例
這篇文章主要介紹了android自定義控件步驟示例,包括為View類(lèi)增加屬性、響應(yīng)用戶消息、自定義回調(diào)函數(shù)等方法2014-01-01Ubuntu16.04 LTS 下安裝 Android Studio 2.2.2 的詳細(xì)步驟
這篇文章主要介紹了Ubuntu16.04 LTS 下安裝 Android Studio 2.2.2 的詳細(xì)步驟,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11Android checkbox的listView具體操作方法
這篇文章主要介紹了Android checkbox的listView具體操作方法,重點(diǎn)就是存儲(chǔ)每個(gè)checkbox的狀態(tài)值,感興趣的小伙伴們可以參考一下2015-12-12Android7.0 工具類(lèi):DiffUtil詳解
這篇文章主要介紹了Android7.0 工具類(lèi):DiffUtil的相關(guān)資料,并附實(shí)例代碼,和實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-09-09Android 實(shí)現(xiàn)可任意拖動(dòng)的懸浮窗功能(類(lèi)似懸浮球)
這篇文章主要介紹了Android 可任意拖動(dòng)的懸浮窗(類(lèi)似懸浮球),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Android LayoutInflater加載布局詳解及實(shí)例代碼
這篇文章主要介紹了Android LayoutInflater加載布局詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02Android利用ConstraintLayout實(shí)現(xiàn)漂亮的動(dòng)畫(huà)詳解
最近在無(wú)意中看到一篇關(guān)于ConstraintLayout的文章,ConstraintLayout是Android Studio 2.2中主要的新增功能之一,下面這篇文章主要給大家介紹了關(guān)于Android利用ConstraintLayout實(shí)現(xiàn)漂亮的動(dòng)畫(huà)的相關(guān)資料,需要的朋友可以參考下。2017-05-05Android 代碼寫(xiě)控件代替XML簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android 代碼寫(xiě)控件代替XML簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05