Flutter动态系统颜色适配插件dynamic_system_colors的使用

Flutter动态系统颜色适配插件dynamic_system_colors的使用

动态系统颜色适配插件 dynamic_system_colors

pub package

dynamic_system_colors 是一个用于根据平台的动态颜色实现创建 Material 颜色方案的 Flutter 插件。目前支持的平台包括:

  • Android S+: 用户壁纸颜色
    • 通过内容颜色创建颜色方案,可以使用 ColorScheme.fromImageProvider
  • Linux: GTK+ 主题的 @theme_selected_bg_color
  • macOS: 应用程序强调色
  • Windows: 强调色或窗口/玻璃颜色

该插件还支持颜色和颜色方案的谐调。

开始使用

在你的 Flutter 项目中添加 dynamic_system_colors 插件:

flutter pub add dynamic_system_colors

在 Dart 文件中导入:

import 'package:dynamic_system_colors/dynamic_system_colors.dart';

特性

构建器小部件

DynamicColorBuilder 是一个状态小部件,它提供了设备的动态颜色的浅色和深色 ColorScheme

DynamicColorBuilder(
  builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
    return ...;
  }
),

插件

DynamicColorBuilder 在后台使用插件与操作系统通信。

颜色和颜色方案谐调

谐调使得向应用中添加新颜色变得更加无缝,通过稍微调整色调和饱和度,使产品的颜色更符合用户的动态颜色。

该插件提供了两种扩展方法来实现这一点:

Color color = Colors.red;
// 将颜色的色调朝向(动态)颜色方案的主色调整。这使得颜色仍然可识别,同时与用户的动态颜色相协调。
harmonizedColor = color.harmonizeWith(colorScheme.primary);

// 对于颜色方案内置的语义颜色执行相同操作
harmonizedColorScheme = colorScheme.harmonized();

详细信息见 harmonization.dart。更多关于自定义颜色和谐调的信息可以在 Material 3 网站上找到。

示例

查看 example/lib/complete_example.dart 获取动态颜色,创建谐调的颜色方案并谐调自定义颜色。

查看 example/lib/accent_color.dart 获取桌面端的强调色。

Example App Screenshot

所有示例都是 示例应用 的一部分。运行示例应用:

cd example
flutter run

测试

import 'package:dynamic_system_colors/test_utils.dart';
import 'package:dynamic_system_colors/samples.dart';

void main() {
  // 为每个测试重置
  setUp(() => DynamicColorTestingUtils.setMockDynamicColors());

  testWidgets('验证使用动态核心调色板', (WidgetTester tester) async {
    DynamicColorTestingUtils.setMockDynamicColors(
      corePalette: SampleCorePalettes.green,
    );

    // ...
});

示例见 example/test/widget_test.dart

开发

示例应用 通过 GitHub 页面托管。更新它:

cd example
flutter build web

完整示例 DEMO

以下是一个完整的示例,展示了如何使用 dynamic_system_colors 插件来获取动态颜色并构建用户界面。

import 'package:flutter/material.dart';
import 'package:dynamic_system_colors/dynamic_system_colors.dart';

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

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    final textTheme = Theme.of(context).textTheme;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Examples')),
        body: Center(
          child: Container(
            constraints: const BoxConstraints(maxWidth: 600), // 设置最大宽度
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                const _ExampleAppButton(
                  title: "动态颜色构建示例",
                  widget: DynamicColorBuilderExample(),
                ),
                const Divider(),
                Padding(
                  padding: const EdgeInsets.all(20),
                  child: Text(
                    '高级示例',
                    style: textTheme.titleMedium,
                  ),
                ),
                const _ExampleAppButton(
                  title: "核心调色板可视化",
                  widget: CorePaletteVisualization(),
                ),
                const _ExampleAppButton(
                  title: "强调色示例",
                  widget: AccentColorExample(),
                ),
                const _ExampleAppButton(
                  title: "谐调示例",
                  widget: HarmonizationExample(),
                ),
                const _ExampleAppButton(
                  title: "高级示例1",
                  widget: AdvancedExample1(),
                ),
                const _ExampleAppButton(
                  title: "高级示例2",
                  widget: AdvancedExample2(),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _ExampleAppButton extends StatelessWidget {
  const _ExampleAppButton({
    required this.title,
    required this.widget,
  });

  final String title;
  final Widget widget;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: ElevatedButton(
        child: Text(title),
        onPressed: () => Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => Scaffold(
              appBar: AppBar(
                title: Text(title, style: const TextStyle(fontSize: 14)),
              ),
              body: Padding(
                  padding: (title == "动态颜色构建示例")
                      ? EdgeInsets.zero
                      : const EdgeInsets.all(16),
                  child: widget),
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter动态系统颜色适配插件dynamic_system_colors的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动态系统颜色适配插件dynamic_system_colors的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter插件dynamic_system_colors的代码案例。这个插件可以帮助你的Flutter应用动态适配系统颜色变化,比如用户在iOS上的暗模式切换。

首先,你需要在你的pubspec.yaml文件中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  dynamic_system_colors: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来获取依赖。

接下来,你可以在你的应用中配置和使用这个插件。以下是一个基本的示例:

  1. 初始化插件

在你的主应用文件(通常是main.dart)中,你需要初始化插件并监听系统颜色变化。

import 'package:flutter/material.dart';
import 'package:dynamic_system_colors/dynamic_system_colors.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    // 初始化插件并监听系统颜色变化
    DynamicSystemColors.initialize().then((_) {
      DynamicSystemColors.addListener(() {
        setState(() {}); // 触发UI重建以应用新颜色
      });
    });
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    DynamicSystemColors.removeListener(() {});
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 使用系统颜色
    final Color systemBackgroundColor = DynamicSystemColors.backgroundColor;
    final Color systemSurfaceColor = DynamicSystemColors.surfaceColor;
    final Color systemOnSurfaceColor = DynamicSystemColors.onSurfaceColor;

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        backgroundColor: systemBackgroundColor,
        scaffoldBackgroundColor: systemSurfaceColor,
        textTheme: TextTheme(
          bodyText1: TextStyle(color: systemOnSurfaceColor),
        ),
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dynamic System Colors Demo'),
        ),
        body: Center(
          child: Text('Check the system color changes!'),
        ),
      ),
    );
  }
}
  1. 使用系统颜色

在上面的代码中,我们通过DynamicSystemColors获取系统颜色,并在ThemeData中应用这些颜色。DynamicSystemColors提供了多种系统颜色属性,如backgroundColorsurfaceColoronSurfaceColor等,你可以根据需求选择使用。

  1. 处理颜色变化

我们通过DynamicSystemColors.addListener方法添加一个监听器,当系统颜色发生变化时,调用setState方法以触发UI重建,从而应用新的系统颜色。

  1. 清理资源

dispose方法中,我们移除监听器并调用WidgetsBinding.instance.removeObserver(this)来清理资源,避免内存泄漏。

这样,你的Flutter应用就能够动态地适配系统颜色变化了。如果你有更多的自定义需求,可以进一步调整和扩展这个基础示例。

回到顶部