Menu
CoddyTech

深色模式开关

本课属于 Coddy Flutter 学习旅程的“适配不同屏幕的布局”单元。第 25 课,共 30 课。

有些人希望只在某个应用中使用深色模式,而不在其他应用中使用。给他们一个切换开关。

themeMode: 和其他设置一样,也可以来自状态。在 MyApp 的 State 中保存一个 bool,MyApp 是构建 MaterialApp 的组件,然后根据它选择模式:

bool _dark = false;

MaterialApp(
  themeMode: _dark ? ThemeMode.dark : ThemeMode.light,
  ...
)

当开关在 setState 中更改 _dark 时,build 会再次运行,MaterialApp 会获得新的模式,所有屏幕都会立即切换主题,并带有短暂的淡入淡出效果。

状态必须保存在 MaterialApp 上方,因为主题是在那里选择的。这就是为什么这里的 MyApp 是一个 StatefulWidget。

challenge icon

挑战

简单

让开关切换主题:

  • 在 onChanged 中,将新值存入 _dark,并放在 setState 中
  • 根据 _dark 设置 MaterialApp 的 themeMode::值为 true 时使用深色主题,值为 false 时使用浅色主题

亲手试试

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _dark = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.indigo,
          brightness: Brightness.dark,
        ),
      ),
      home: Scaffold(
        appBar: AppBar(title: const Text('Night Reader')),
        body: Center(
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Text('Dark mode', style: TextStyle(fontSize: 20)),
              const SizedBox(width: 12),
              Switch(
                value: _dark,
                onChanged: (value) {},
              ),
            ],
          ),
        ),
      ),
    );
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

适配不同屏幕的布局中的所有课

自己练习: Flutter 在线编译器