深色模式(Dark Mode),也被稱為暗黑模式,是一種高對比度,或者反色模式的顯示模式,開啟之後在夜間可以緩解疲勞,更易於閱讀,同時也能在一定程度上達到省電的效果。iOS和安卓分別從 iOS 13 和 Android 10(不同廠商不盡相同,部分 Android 9 也支援) 開始加入深色模式的支援,各大瀏覽器紛紛開始支援深色模式,強如微信也終於在 iOS 客戶端 7.0.12、Android 客戶端 7.0.13 支援了深色模式,等網頁端適配深色模式後將更進一步提高使用者體驗的一致性。
Flutter作為一個先進的跨平臺框架,自然也考慮到了深色模式的使用,我在上一篇文章《Flutter主題切換——讓你的APP也能一鍵換膚》的結尾提到了Brightness brightness
屬性可用於適配跟隨系統的DarkMode,我們可以直接在MaterialApp
的darkTheme
選項中使用
MaterialApp(
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
),
);
複製程式碼
也可以寫成:
darkTheme: ThemeData.dark()
複製程式碼
這樣寫的好處是,使用者無需單獨設定深/淺色模式,完全根據系統設定來切換。
但白天不懂夜的黑,有的人就是喜歡一套深色主題用一天,這時就需要使用者可以手動開啟深色模式了。
我們先來看下實現的效果:
手動開啟深色模式
其實思路和上一篇文章類似,通過shared_preferences儲存使用者設定,通過Provider實現狀態管理,這兩個依賴的使用我在上一篇文章中已經介紹了,這裡就不多說了。詳情點選?Flutter主題切換——讓你的APP也能一鍵換膚。
新增依賴
我們在pubspec.yaml
檔案中新增如下內容:
provider: ^4.0.5
flustars: ^0.2.6+1
複製程式碼
深色模式狀態管理類
import 'package:flustars/flustars.dart';
import 'package:flutter/material.dart';
import 'package:flutterchallenge/constant.dart';
class DarkModeProvider with ChangeNotifier {
/// 深色模式 0: 關閉 1: 開啟 2: 隨系統
int _darkMode;
int get darkMode => _darkMode;
void changeMode(int darkMode) async {
_darkMode = darkMode;
notifyListeners();
SpUtil.putInt(SpConstant.DARK_MODE, darkMode);
}
}
複製程式碼
我們通過changeMode()
函式來進行模式的切換,其中notifyListeners();
用於通知頂層容器狀態的變化,SpUtil.putInt(SpConstant.DARK_MODE, darkMode);
用於儲存使用者設定。
修改MaterialApp
接下來我們需要在頂層容器中配置我們的狀態管理類,和上文類似,這裡同樣使用了MultiProvider
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: DarkModeProvider()),
],
child: Consumer<DarkModeProvider>(
builder: (context, darkModeProvider, _) {
return darkModeProvider.darkMode == 2
? MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
darkTheme: ThemeData.dark(),
home: MyHomePage(title: 'Flutter Challenge Demo'),
)
: MaterialApp(
title: 'Flutter Demo',
theme: darkModeProvider.darkMode == 1
? ThemeData.dark()
: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Challenge Demo'),
);
},
),
);
}
}
複製程式碼
如果手動控制是否開啟夜間模式,可以設定MaterialApp
的theme
選項為ThemeData.dark()
theme: ThemeData.dark()
複製程式碼
因為需要同時保留隨系統自動切換與手動切換,而darkTheme
選項和theme
又有衝突,所以這裡需要根據darkModeProvider.darkMode
的取值來渲染不同的MaterialApp
,如果是手動模式再根據darkModeProvider.darkMode
的取值來渲染不同的theme
。
選擇深色模式
接下來如果想要切換深色模式,我們只需要執行下面這行程式碼即可。
Provider.of<DarkModeProvider>(context, listen: false).changeMode(1);
複製程式碼
其中,0表示淺色,1表示深色,2表示跟隨系統。
至此,本文內容結束,這裡我們頭腦風暴一下,能否將上文中提到的主題選擇和本文的深色模式結合起來呢?歡迎各位在評論區留言。
最後
這裡說下最近遇到的一件很不痛快的事情,在之前的文章中,示例程式碼需要關注我的公眾號才可獲得,結果就被某個人評論說我割韭菜。
我不知道他是白嫖習慣了還是怎麼的,程式碼是我自己付出努力寫的,從頭到尾我就沒說過程式碼是開源的,憑什麼要無緣無故給你白嫖程式碼?
說這些其實也是希望看到這裡的讀者不要養成總是白嫖他人的習慣,如果覺得我的文章對你有所幫助,不妨給個贊 ? 或者關注支援一下。
對了,本期的程式碼?:github.com/YueYongDev/…