A list,

The dark mode of Flutter and the following system Settings are relatively simple. What I need to pay attention to is to try to use the color and style of Theme in the development process. The biggest problems I encountered in the development process are some problems with the provider, maybe because I used a new version and found many articles online, so I always encountered some problems. The adaptation of dark mode in this paper is achieved by modifying themeMode for your reference.

2. Environment introduction

1. The Flutter: 2.0.3

2. The Dart: 2.12.0

3. The provider: 5.0.0

State management, used to switch topics at run time

4. Shared_preferences: at 2.0.5

Data persistence, used to save the currently selected theme so that the user-selected theme can be read and used at the next startup

environment:
  sdk: "> = 2.12.0 < 3.0.0"

dependencies:
  flutter:
    sdk: flutter

	# Ignoring some dependencies...

  # shared_preferences https://pub.flutter-io.cn/packages/shared_preferences
  shared_preferences: ^ at 2.0.5
  # https://github.com/rrousselGit/provider/blob/master/resources/translations/zh-CN/README.md global state management
  provider: ^ 5.0.0

Copy the code

Three, themes,

1. ThemeData

factory ThemeData({
    Brightness brightness, // Apply theme brightness, optional (dark, light)
    VisualDensity visualDensity, // Visual density
    MaterialColor primarySwatch, // Set primaryColor to overwrite the background color
    Color primaryColor, // Main part background color (navigation, tabBar, etc.)
    Brightness primaryColorBrightness, // primaryColor brightness
    Color primaryColorLight, // A lighter version of primaryColor
    Color primaryColorDark, // The darker version of primaryColor
    Color accentColor, // Foreground color (text, buttons, etc.)
    Brightness accentColorBrightness, // accentColor brightness
    Color canvasColor, // The default color of materialType.canvas
    Color shadowColor, // Shadow color
    Color scaffoldBackgroundColor, // The background colour of the Scaffold. The background color of a typical Material application or page within an application
    Color bottomAppBarColor, // The default color of BottomAppBar
    Color cardColor, // The color of Card
    Color dividerColor, // The colors of the Divider and PopupMenuDivider are also used between listtiles, between rows of the DataTable, etc.
    Color focusColor, // Highlight the color
    Color hoverColor, // hoverColor
    Color highlightColor, // Highlight color, select the highlight color to use during splash animation, or to indicate items in the menu.
    Color splashColor, // The color of the ink splash. InkWell
    InteractiveInkFeatureFactory splashFactory, // Define the appearance of the splash produced by the InkWell and InkResponse reactions.
    Color selectedRowColor, // Use to highlight the color of the selected row.
    Color unselectedWidgetColor, // The color used for widgets that are inactive (but enabled). For example, an unchecked check box. This is usually contrasted with accentColor. Also see disabledColor.
    Color disabledColor, // Disable the color of the part in the state, regardless of its current state. For example, a disabled check box (which can be checked or unchecked).
    Color buttonColor, // The default padding color for Material used in the RaisedButton.
    ButtonThemeData buttonTheme, // Define the default configuration of the button widget,
    ToggleButtonsThemeData toggleButtonsTheme, // Toggle button themes
    Color secondaryHeaderColor, // The color of the PaginatedDataTable title when the row is selected.
    Color textSelectionColor, // The color of the text selected by the text box, such as TextField
    Color cursorColor, // The color of the cursor in a text box, such as TextField
    Color textSelectionHandleColor, // Adjusts the color of the handle to the currently selected text section.
    Color backgroundColor, // A color that contrasts with the main color, e.g. used as the rest of a progress bar.
    Color dialogBackgroundColor, // The background color of the Dialog element
    Color indicatorColor, // The color of the selected TAB indicator in the TAB.
    Color hintColor, // The color used to prompt text or placeholder text, as in TextField.
    Color errorColor, // The color used for input validation errors, such as in TextField
    Color toggleableActiveColor, // The color used to highlight the active state of swappable widgets like Switch, Radio, and Checkbox.
    String fontFamily, // Text font
    TextTheme textTheme, // The color of the text contrasts with the color of the card and canvas.
    TextTheme primaryTextTheme, // Contrast the text theme with primaryColor
    TextTheme accentTextTheme, // Contrast the text theme with accentColor.
    InputDecorationTheme inputDecorationTheme, // Default InputDecorator, TextField, and TextFormField values based on this topic.
    TabBarTheme tabBarTheme, // Theme for customizing the size, shape, and color of TAB bar indicators.
    TooltipThemeData tooltipTheme, / / the tooltip theme
    CardTheme cardTheme, // Card color and style
    AppBarTheme appBarTheme, / / the appBar theme
    ColorScheme colorScheme, // There are 13 colors, which can be used to configure the colors of most components.
    NavigationRailThemeData navigationRailTheme, // Navigate to the sidebar theme
  	// ...
  })
Copy the code

2. main.dart or MaterialApp

DarkTheme is the default theme, darkTheme is the dark theme, themeMode is the current theme, the optional values of system, light, dark, only when th ‘ ’eme and darkTheme are set. Our Theme and darkTheme both use the ThemeData object directly, and gave it the Thumbnail version instead of the thumbnail version. It is also convenient to change the style. Of course, you can also pull out the thumbnail version.

MaterialApp(
  theme: ThemeData(
    brightness: Brightness.light,
    // scaffoldBackgroundColor: Color(0xFFF5F5F9),
  ),
  darkTheme: ThemeData(
    brightness: Brightness.dark,
    // scaffoldBackgroundColor: Color(0xFFF5F5F9),
  ),
  themeMode: context.watch<ThemeModel>().theme
);
Copy the code

4. Global configuration

The global configuration is a write initialization operation before loading the MaterialApp. Referring to the ebook “Flutter Practice”, the SharedPreferences of Flutter are asynchronously initialized, and the cache of Dio network requests also needs to be initialized in advance. SpUtils SharedPreferences use the static properties of the Global configuration.

1. Global

class Global {
  static late SharedPreferences prefs;

  static ThemeMode theme = ThemeMode.light;

  // Whether it is a release
  static bool get isRelease => bool.fromEnvironment("dart.vm.product");

  // Initializes the global information, which is executed when the APP starts
  static Future init() async {
    WidgetsFlutterBinding.ensureInitialized();
    prefs = await SharedPreferences.getInstance();

    // The subject of the current local storage
    String themeValue = await SpUtils.instance.getStorage(SpConstants.skin);
    theme = themeStringToThemeMode(themeValue);

    // Initializes the network request configurationHttpManager(); }}Copy the code

2. main.dart

// use runApp when Global is loaded
Global.init().then((e) => runApp());
Copy the code

3. themeStringToThemeMode()

String to 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;
}
Copy the code

Use state management (Provider) to switch topics

“> < p style =” max-width: 100%; clear: both; min-height: 1em

1. Build the theme Model

class ThemeModel extends ChangeNotifier {

  // Gets the current theme. If the theme is set, the default is light-colored mode
  ThemeMode get theme => Global.theme;

  // When the theme changes, notify its dependencies and the new theme takes effect immediately
  set theme(ThemeMode themeMode) {
    if(themeMode ! = theme) { Global.theme = themeMode; notifyListeners(); }}}Copy the code

2. Main. dart(listens for value changes)

Here is the complete code for the main.dart file. The following ways of using providers may be different from many articles on the web, but they are the latest recommendations in the official documentation. Watch ().theme reads the theme stored in the current provider

void main() {
  // The top status bar is transparent
  SystemChrome.setSystemUIOverlayStyle(
      SystemUiOverlayStyle(statusBarColor: Colors.transparent));
  Global.init().then((e) => runApp(
        MultiProvider(
            providers: [ListenableProvider<ThemeModel>(create: (_) => ThemeModel())],
            builder: (context, child) {
              returnWanAndroid(); }))); }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: 'Play Android-Flutter Version',); }}Copy the code

3. Switch topics

Modify the values saved in the provider.

// themeStringToThemeMode method code is written above
context.read<ThemeModel>().theme = themeStringToThemeMode(value);
Copy the code

Six, the source code

– Source: github.com/sdwfqin/flu…