Flutter深色模式適配的實現
一、簡介
Flutter的深色模式以及跟隨系統設置比較簡單,我感覺需要註意的是開發過程中盡量使用Theme中的顏色與樣式,開發過程中遇到的比較大的坑就是provider的一些問題,可能是因為我用的版本新一些,網上找瞭很多文章,總會遇到一些問題。本文的深色模式適配是通過修改themeMode來實現的,供諸位有緣人參考。
二、環境介紹
1. Flutter: 2.0.3
2. Dart: 2.12.0
3. provider: 5.0.0
狀態管理,用於運行時切換主題
4. shared_preferences: 2.0.5
數據持久化,用於保存當前選中的主題,以便下次啟動時讀取使用用戶選擇的主題
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 # 全局狀態管理 https://github.com/rrousselGit/provider/blob/master/resources/translations/zh-CN/README.md provider: ^5.0.0
三、主題
1. ThemeData
factory ThemeData({ Brightness brightness, // 應用主題亮度,可選(dark、light) VisualDensity visualDensity, // 視覺密度 MaterialColor primarySwatch, // 主要樣式,設置primaryColor後該背景色會被覆蓋 Color primaryColor, // 主要部分背景顏色(導航和tabBar等) Brightness primaryColorBrightness, // primaryColor的亮度 Color primaryColorLight, // primaryColor的淺色版 Color primaryColorDark, // primaryColor的深色版 Color accentColor, // 前景色(文本,按鈕等) Brightness accentColorBrightness, // accentColor的亮度 Color canvasColor, // MaterialType.canvas 的默認顏色 Color shadowColor, // 陰影顏色 Color scaffoldBackgroundColor, // Scaffold的背景顏色。典型Material應用程序或應用程序內頁面的背景顏色 Color bottomAppBarColor, // BottomAppBar的默認顏色 Color cardColor, // Card的顏色 Color dividerColor, // Divider和PopupMenuDivider的顏色,也用於ListTile之間、DataTable的行之間等。 Color focusColor, // 突出顏色 Color hoverColor, // hoverColor Color highlightColor, // 高亮顏色,選中在潑墨動畫期間使用的突出顯示顏色,或用於指示菜單中的項。 Color splashColor, // 墨水飛濺的顏色。InkWell InteractiveInkFeatureFactory splashFactory, // 定義由InkWell和InkResponse反應產生的墨濺的外觀。 Color selectedRowColor, // 用於突出顯示選定行的顏色。 Color unselectedWidgetColor, // 用於處於非活動(但已啟用)狀態的小部件的顏色。例如,未選中的復選框。通常與accentColor形成對比。也看到disabledColor。 Color disabledColor, // 禁用狀態下部件的顏色,無論其當前狀態如何。例如,一個禁用的復選框(可以選中或未選中)。 Color buttonColor, // RaisedButton按鈕中使用的Material 的默認填充顏色。 ButtonThemeData buttonTheme, // 定義按鈕部件的默認配置, ToggleButtonsThemeData toggleButtonsTheme, // 切換按鈕的主題 Color secondaryHeaderColor, // 選定行時PaginatedDataTable標題的顏色。 Color textSelectionColor, // 文本框中文本選擇的顏色,如TextField Color cursorColor, // 文本框中光標的顏色,如TextField Color textSelectionHandleColor, // 調整當前選定的文本部分的句柄的顏色。 Color backgroundColor, // 與主色形成對比的顏色,例如用作進度條的剩餘部分。 Color dialogBackgroundColor, // Dialog元素的背景顏色 Color indicatorColor, // 選項卡中選定的選項卡指示器的顏色。 Color hintColor, // 用於提示文本或占位符文本的顏色,例如在TextField中。 Color errorColor, // 用於輸入驗證錯誤的顏色,例如在TextField中 Color toggleableActiveColor, // 用於突出顯示Switch、Radio和Checkbox等可切換小部件的活動狀態的顏色。 String fontFamily, // 文本字體 TextTheme textTheme, // 文本的顏色與卡片和畫佈的顏色形成對比。 TextTheme primaryTextTheme, // 與primaryColor形成對比的文本主題 TextTheme accentTextTheme, // 與accentColor形成對比的文本主題。 InputDecorationTheme inputDecorationTheme, // 基於這個主題的 InputDecorator、TextField和TextFormField的默認InputDecoration值。 TabBarTheme tabBarTheme, // 用於自定義選項卡欄指示器的大小、形狀和顏色的主題。 TooltipThemeData tooltipTheme, // tooltip主題 CardTheme cardTheme, // Card的顏色和樣式 AppBarTheme appBarTheme, // appBar主題 ColorScheme colorScheme, // 擁有13種顏色,可用於配置大多數組件的顏色。 NavigationRailThemeData navigationRailTheme, // 導航邊欄主題 // ... })
2. main.dart or MaterialApp
theme為默認主題,darkTheme為深色主題,themeMode為當前使用哪個主題,可選值system、light、dark,隻有在th“eme與darkTheme都設置的時候才會生效,我們的theme與darkTheme都直接使用ThemeData對象,給他指定瞭brightness,而不是使用這樣感覺可以方便修改樣式,當然也可以抽出來封裝一下,我這沒有去處理。
MaterialApp( theme: ThemeData( brightness: Brightness.light, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), darkTheme: ThemeData( brightness: Brightness.dark, // scaffoldBackgroundColor: Color(0xFFF5F5F9), ), themeMode: context.watch<ThemeModel>().theme );
四、全局配置
全局配置是在MaterialApp加載之前進行一寫初始化操作,參考瞭《Flutter實戰》電子書,Flutter當中SharedPreferences是異步初始化,還有Dio網絡請求的緩存也需要提前初始化,我們這裡SharedPreferences加載完之後在進行之後的操作,SpUtils中的SharedPreferences使用的Global全局配置中的靜態屬性。
1. Global
class Global { static late SharedPreferences prefs; static ThemeMode theme = ThemeMode.light; // 是否為release版 static bool get isRelease => bool.fromEnvironment("dart.vm.product"); //初始化全局信息,會在APP啟動時執行 static Future init() async { WidgetsFlutterBinding.ensureInitialized(); prefs = await SharedPreferences.getInstance(); // 當前本地存儲的主題 String themeValue = await SpUtils.instance.getStorage(SpConstants.skin); theme = themeStringToThemeMode(themeValue); //初始化網絡請求相關配置 HttpManager(); } }
2. main.dart
// Global加載完成後掉用runApp Global.init().then((e) => runApp());
3. themeStringToThemeMode()
字符串轉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; }
五、使用狀態管理(provider)切換主題
> 此處大坑,處處勸退,感謝Flutter provider勸退經歷這篇文章
1. 構建主題Model
class ThemeModel extends ChangeNotifier { // 獲取當前主題,如果為設置主題,則默認使用淺色模式 ThemeMode get theme => Global.theme; // 主題改變後,通知其依賴項,新主題會立即生效 set theme(ThemeMode themeMode) { if (themeMode != theme) { Global.theme = themeMode; notifyListeners(); } } }
2. main.dart(監聽值變化)
此處為main.dart文件的完整代碼,下面有關provider的一些使用方式可能與網上很多文章不一樣的,但是這都是官網文檔的最新推薦使用方式。讀取當前provider中存儲的主題context.watch<ThemeModel>().theme
void main() { //頂部狀態欄透明 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方法代碼在上面有寫 context.read<ThemeModel>().theme = themeStringToThemeMode(value);
六、源碼
– 源碼:github.com/sdwfqin/flutter_wanandroid
到此這篇關於Flutter深色模式適配的實現的文章就介紹到這瞭,更多相關Flutter深色模式適配內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- None Found