Flutter適配夜間模式

夜間模式(Dark Mode),也被稱為暗黑模式或深色模式,是一種高對比度,或者反色模式的顯示模式,開啟之後在夜間可以緩解疲勞,更易於閱讀,同時也能在一定程度上達到省電的效果。蘋果方面有表示,明年3月份還不適配深色模式的App都要從App Store下架

夜間模式跟隨系統

使用MaterialApp的darkTheme選項,可以很方便地適配跟隨系統的DarkMode:

<code>MaterialApp( 
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
),
);/<code>

也可直接寫做

<code>darkTheme: ThemeData.dark()/<code>
  • 這種方式是自動跟隨iOS/Android的系統設置來切換的,無需用戶再單獨設置

手動開啟夜間模式

上述的跟隨系統自動切換暗黑模式的體驗可能並不是很好,比如用戶不喜歡夜間模式或者App的夜間模式配色適配並不是很好,這就會導致用戶無法手動控制app的夜間模式或者只能關閉系統的設置。因此我們可以增加手動控制以及跟隨系統的選項,讓用戶選擇是否開啟以及開啟的方式。

保存用戶配置

在flutter中可以使用shared_preferences來保存用戶的配置數據,具體使用方法詳見:shared_preferences使用

狀態管理

主題的手動切換是影響全局的,如果通過常規的數據流向很難做到。常見的幾種狀態管理:

  • InheritedWidget
  • Scoped model
  • BLoC
  • Redux
  • Provider

Provider是Google I/O 2019大會宣佈的現在官方推薦的狀態管理方式,我們需要在設置頁裡面通過用戶設置,把變更狀態共享給其他Widget,這裡採用Provider這種方式來實現狀態共享。

通用夜間模式Provider Model類

<code>import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

class DarkModeModel with ChangeNotifier {
/// 夜間模式 0: 關閉 1: 開啟 2: 隨系統
int _darkMode;

static const Map darkModeMap = {
0: "關閉",
1: "開啟",
2: "跟隨系統"
};

static const String STORE_KEY = 'darkMode';

SharedPreferences _prefs;

int get darkMode => _darkMode;

DarkModeModel() {
_init();
}

void _init() async {
this._prefs = await SharedPreferences.getInstance();
int localMode = this._prefs.getInt(STORE_KEY);
changeMode(localMode ?? 0);
}

void changeMode(int darkMode) async {

_darkMode = darkMode;

notifyListeners();

SharedPreferences prefs = this._prefs ?? SharedPreferences.getInstance();

await prefs.setInt(STORE_KEY, darkMode);
}
}
/<code>

MaterialApp修改

如果手動控制是否開啟夜間模式,可以設置MaterialApp的theme選項為ThemeData.dark()

<code>theme: ThemeData.dark()/<code>

因為需要同時保留隨系統自動切換與手動切換,而darkTheme選項和theme又有衝突,所以這裡需要根據darkModeModel.darkMode的取值來渲染不同的MaterialApp,如果是手動模式再根據darkModeModel.darkMode的取值來渲染不同的theme。

<code>MultiProvider(
providers: [
ChangeNotifierProvider(builder: (_) => DarkModeModel())
],
child: Consumer<darkmodemodel>(

builder: (context, darkModeModel, _) {
return darkModeModel.darkMode == 2
? MaterialApp(
title: '特效君',
theme: ThemeData(
primarySwatch: Colors.blue,
),
darkTheme: ThemeData.dark(),
home: MainPage(title: '特效君'),
)
: MaterialApp(
title: '特效君',
theme: darkModeModel.darkMode == 1
? ThemeData.dark()
: ThemeData(
primarySwatch: Colors.blue,
),
home: MainPage(title: '特效君'),
);
},
),
)
/<darkmodemodel>/<code>

效果

這樣我們就可以給用戶提供自動跟隨系統切換以及手動控制的選項了

Flutter適配夜間模式

跟隨系統開啟夜間模式


Flutter適配夜間模式

手動開啟關閉夜間模式


分享到:


相關文章: