快速適配 Flutter 之深色模式

巴格梅克發表於2020-05-06

快速適配 Flutter 之深色模式

深色模式(Dark Mode),也被稱為暗黑模式,是一種高對比度,或者反色模式的顯示模式,開啟之後在夜間可以緩解疲勞,更易於閱讀,同時也能在一定程度上達到省電的效果。iOS和安卓分別從 iOS 13 和 Android 10(不同廠商不盡相同,部分 Android 9 也支援) 開始加入深色模式的支援,各大瀏覽器紛紛開始支援深色模式,強如微信也終於在 iOS 客戶端 7.0.12、Android 客戶端 7.0.13 支援了深色模式,等網頁端適配深色模式後將更進一步提高使用者體驗的一致性。

Flutter作為一個先進的跨平臺框架,自然也考慮到了深色模式的使用,我在上一篇文章《Flutter主題切換——讓你的APP也能一鍵換膚》的結尾提到了Brightness brightness屬性可用於適配跟隨系統的DarkMode,我們可以直接在MaterialAppdarkTheme選項中使用

MaterialApp( 
    theme: ThemeData( 
        brightness: Brightness.light, 
        primaryColor: Colors.blue, 
    ), 
    darkTheme: ThemeData( 
        brightness: Brightness.dark, 
    ),
);
複製程式碼

也可以寫成:

darkTheme: ThemeData.dark()
複製程式碼

這樣寫的好處是,使用者無需單獨設定深/淺色模式,完全根據系統設定來切換。

但白天不懂夜的黑,有的人就是喜歡一套深色主題用一天,這時就需要使用者可以手動開啟深色模式了。

我們先來看下實現的效果:

快速適配 Flutter 之深色模式

手動開啟深色模式

其實思路和上一篇文章類似,通過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'),
                );
        },
      ),
    );
  }
}
複製程式碼

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

theme: ThemeData.dark()
複製程式碼

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

選擇深色模式

接下來如果想要切換深色模式,我們只需要執行下面這行程式碼即可。

Provider.of<DarkModeProvider>(context, listen: false).changeMode(1);
複製程式碼

其中,0表示淺色,1表示深色,2表示跟隨系統。

至此,本文內容結束,這裡我們頭腦風暴一下,能否將上文中提到的主題選擇和本文的深色模式結合起來呢?歡迎各位在評論區留言。

最後

這裡說下最近遇到的一件很不痛快的事情,在之前的文章中,示例程式碼需要關注我的公眾號才可獲得,結果就被某個人評論說我割韭菜。

快速適配 Flutter 之深色模式

我不知道他是白嫖習慣了還是怎麼的,程式碼是我自己付出努力寫的,從頭到尾我就沒說過程式碼是開源的,憑什麼要無緣無故給你白嫖程式碼?

說這些其實也是希望看到這裡的讀者不要養成總是白嫖他人的習慣,如果覺得我的文章對你有所幫助,不妨給個贊 ? 或者關注支援一下。

對了,本期的程式碼?:github.com/YueYongDev/…

快速適配 Flutter 之深色模式

相關文章