Flutter动态主题颜色插件dynamic_color_theme的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter动态主题颜色插件dynamic_color_theme的使用

动态主题颜色插件简介

dynamic_color_theme插件允许您动态更改应用的主题颜色,并根据新的颜色自动切换浅色和深色模式。此外,通过将颜色和深色模式保存到共享偏好设置中,可以跨重启持久化颜色值。

演示

安装

pubspec.yaml文件中添加依赖:

dependencies:
  dynamic_color_theme: ^2.0.0

导入插件:

import 'package:dynamic_color_theme/dynamic_color_theme.dart';

如果您想使用内置的颜色选择器对话框,还需导入以下内容:

import 'package:dynamic_color_theme/color_picker_dialog.dart';

使用方法

包裹主小部件

为了使用dynamic_color_theme,您需要将主小部件包裹在DynamicColorTheme中:

const kFuchsia = const Color(0xFF880E4F);
const kWhite = Colors.white;
const kLightGrey = const Color(0xFFE8E8E8);
const kDarkGrey = const Color(0xFF303030);

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return DynamicColorTheme(
      data: (Color color, bool isDark) {
        return _buildTheme(color, isDark); // 自定义构建主题的方法
      },
      defaultColor: kFuchsia,
      defaultIsDark: false,
      themedWidgetBuilder: (BuildContext context, ThemeData theme) {
        return MaterialApp(
          home: MyHomePage(title: 'Dynamic Color Theme'),
          theme: theme,
          title: 'Flutter Demo',
        );
      },
    );
  }

  // 示例构建主题的方法
  ThemeData _buildTheme(Color accentColor, bool isDark) {
    final ThemeData base = isDark ? ThemeData.dark() : ThemeData.light();
    final Color primaryColor = isDark ? kDarkGrey : kWhite;

    return base.copyWith(
      accentColor: accentColor,
      accentTextTheme: _buildTextTheme(base.accentTextTheme, accentColor),
      cardColor: primaryColor,
      floatingActionButtonTheme: base.floatingActionButtonTheme.copyWith(
        backgroundColor: accentColor,
      ),
      iconTheme: base.iconTheme.copyWith(
        color: accentColor,
      ),
      primaryColor: primaryColor,
      primaryIconTheme: base.primaryIconTheme.copyWith(
        color: accentColor,
      ),
      primaryTextTheme: _buildTextTheme(base.primaryTextTheme, accentColor),
      scaffoldBackgroundColor: primaryColor,
      textSelectionTheme: _buildTextSelectionTheme(base.textSelectionTheme, accentColor, isDark),
      textTheme: _buildTextTheme(base.textTheme, accentColor),
    );
  }

  TextTheme _buildTextTheme(TextTheme base, Color color) {
    return base.copyWith(
      bodyText2: base.bodyText2!.copyWith(
        fontSize: 16,
      ),
      bodyText1: base.bodyText1!.copyWith(
        color: color,
        fontSize: 16,
        fontWeight: FontWeight.bold,
      ),
      button: base.button!.copyWith(
        color: color,
      ),
      caption: base.caption!.copyWith(
        color: color,
        fontSize: 14,
      ),
      headline5: base.headline5!.copyWith(
        color: color,
        fontSize: 24,
      ),
      subtitle1: base.subtitle1!.copyWith(
        color: color,
        fontSize: 18,
      ),
      headline6: base.headline6!.copyWith(
        color: color,
        fontSize: 20,
        fontWeight: FontWeight.bold,
      ),
    );
  }

  TextSelectionThemeData _buildTextSelectionTheme(TextSelectionThemeData base, Color accentColor, bool isDark) {
    return base.copyWith(
      cursorColor: accentColor,
      selectionColor: isDark ? kDarkGrey : kLightGrey,
      selectionHandleColor: accentColor,
    );
  }
}

更改主题

您可以使用提供的函数来更改主题:

void changeColor(Color newColor) {
  DynamicColorTheme.of(context).setColor(
    color: newColor,
    shouldSave: true, // 保存到共享偏好设置
  );
}

void changeIsDark(bool isDark) {
  DynamicColorTheme.of(context).setIsDark(
    isDark: isDark,
    shouldSave: true, // 保存到共享偏好设置
  );
}

void resetTheme() {
  DynamicColorTheme.of(context).resetToSharedPrefsValues();
}

颜色选择器对话框

插件还提供了一个颜色选择器对话框,可以方便地选择颜色并切换深色模式。以下是使用示例:

颜色选择器对话框

可取消的对话框

showDialog(
  barrierDismissible: false,
  builder: (BuildContext context) {
    return ColorPickerDialog(
      defaultColor: kFuchsia,
      defaultIsDark: false,
    );
  },
  context: context,
);

不可取消的对话框

showDialog(
  builder: (BuildContext context) {
    return WillPopScope(
      child: ColorPickerDialog(
        defaultColor: kFuchsia,
        defaultIsDark: false,
      ),
      onWillPop: () async {
        // 如果用户点击对话框外部,重置为共享偏好设置中的值
        DynamicColorTheme.of(context).resetToSharedPrefsValues();
        return true;
      },
    );
  },
  context: context,
);

完整示例Demo

以下是一个完整的示例代码,展示了如何使用dynamic_color_theme插件创建一个带有动态主题颜色的应用程序:

import 'package:dynamic_color_theme/color_picker_dialog.dart';
import 'package:dynamic_color_theme/dynamic_color_theme.dart';
import 'package:flutter/material.dart';

const kFuchsia = const Color(0xFF880E4F);
const kWhite = Colors.white;
const kLightGrey = const Color(0xFFE8E8E8);
const kDarkGrey = const Color(0xFF303030);

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return DynamicColorTheme(
      data: (Color color, bool isDark) {
        return _buildTheme(color, isDark);
      },
      defaultColor: kFuchsia,
      defaultIsDark: false,
      themedWidgetBuilder: (BuildContext context, ThemeData theme) {
        return MaterialApp(
          home: MyHomePage(title: 'Dynamic Color Theme'),
          theme: theme,
          title: 'Flutter Demo',
        );
      },
    );
  }

  ThemeData _buildTheme(Color accentColor, bool isDark) {
    final ThemeData base = isDark ? ThemeData.dark() : ThemeData.light();
    final Color primaryColor = isDark ? kDarkGrey : kWhite;

    return base.copyWith(
      accentColor: accentColor,
      accentTextTheme: _buildTextTheme(base.accentTextTheme, accentColor),
      cardColor: primaryColor,
      floatingActionButtonTheme: base.floatingActionButtonTheme.copyWith(
        backgroundColor: accentColor,
      ),
      iconTheme: base.iconTheme.copyWith(
        color: accentColor,
      ),
      primaryColor: primaryColor,
      primaryIconTheme: base.primaryIconTheme.copyWith(
        color: accentColor,
      ),
      primaryTextTheme: _buildTextTheme(base.primaryTextTheme, accentColor),
      scaffoldBackgroundColor: primaryColor,
      textSelectionTheme: _buildTextSelectionTheme(base.textSelectionTheme, accentColor, isDark),
      textTheme: _buildTextTheme(base.textTheme, accentColor),
    );
  }

  TextTheme _buildTextTheme(TextTheme base, Color color) {
    return base.copyWith(
      bodyText2: base.bodyText2!.copyWith(
        fontSize: 16,
      ),
      bodyText1: base.bodyText1!.copyWith(
        color: color,
        fontSize: 16,
        fontWeight: FontWeight.bold,
      ),
      button: base.button!.copyWith(
        color: color,
      ),
      caption: base.caption!.copyWith(
        color: color,
        fontSize: 14,
      ),
      headline5: base.headline5!.copyWith(
        color: color,
        fontSize: 24,
      ),
      subtitle1: base.subtitle1!.copyWith(
        color: color,
        fontSize: 18,
      ),
      headline6: base.headline6!.copyWith(
        color: color,
        fontSize: 20,
        fontWeight: FontWeight.bold,
      ),
    );
  }

  TextSelectionThemeData _buildTextSelectionTheme(TextSelectionThemeData base, Color accentColor, bool isDark) {
    return base.copyWith(
      cursorColor: accentColor,
      selectionColor: isDark ? kDarkGrey : kLightGrey,
      selectionHandleColor: accentColor,
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  Widget build(BuildContext context) {
    Color color = DynamicColorTheme.of(context).color;
    bool isDark = DynamicColorTheme.of(context).isDark;

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Center(
            child: Text('当前颜色是 $color,是否为深色模式: $isDark'),
          ),
          TextButton(
            child: Text(
              '切换深色模式',
              style: Theme.of(context).textTheme.button,
            ),
            onPressed: () {
              DynamicColorTheme.of(context).setIsDark(
                isDark: !isDark,
                shouldSave: true,
              );
            },
          ),
          TextButton(
            child: Text(
              '设置颜色为洋红色!',
              style: Theme.of(context).textTheme.button,
            ),
            onPressed: () {
              DynamicColorTheme.of(context).setColor(
                color: kFuchsia,
                shouldSave: true,
              );
            },
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton.extended(
        backgroundColor: color,
        icon: Icon(Icons.color_lens),
        label: Text('选择颜色'),
        onPressed: () {
          showDialog(
            builder: (BuildContext context) {
              return WillPopScope(
                child: ColorPickerDialog(
                  defaultColor: kFuchsia,
                  defaultIsDark: false,
                  title: '选择你的命运',
                  cancelButtonText: '算了',
                  confirmButtonText: '好的',
                  shouldAutoDetermineDarkMode: true,
                  shouldShowLabel: true,
                ),
                onWillPop: () async {
                  DynamicColorTheme.of(context).resetToSharedPrefsValues();
                  return true;
                },
              );
            },
            context: context,
          );
        },
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用Flutter中的dynamic_color_theme插件来实现动态主题颜色切换的代码示例。这个插件允许你根据用户的系统主题(如暗模式和亮模式)自动调整你的应用主题。

首先,确保你已经在pubspec.yaml文件中添加了dynamic_color_theme依赖:

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

然后,运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤设置你的应用以支持动态主题颜色。

1. 定义主题数据

在你的main.dart文件中,首先定义你的主题数据,包括亮模式和暗模式的颜色方案。

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

final LightColorScheme lightScheme = LightColorScheme(
  primary: Colors.blue,
  onPrimary: Colors.white,
  surface: Colors.white,
  onSurface: Colors.black,
  // 定义其他颜色...
);

final DarkColorScheme darkScheme = DarkColorScheme(
  primary: Colors.blueGrey,
  onPrimary: Colors.white,
  surface: Colors.black,
  onSurface: Colors.white,
  // 定义其他颜色...
);

2. 创建DynamicTheme

使用DynamicTheme包装你的MaterialApp,并设置动态颜色方案。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DynamicTheme(
      defaultBrightness: Brightness.light, // 初始亮度
      data: (Brightness brightness) {
        return ThemeData(
          brightness: brightness,
          colorScheme: brightness == Brightness.light
              ? ColorScheme.fromSwatch(
                  primarySwatch: lightScheme.primary,
                ).copyWith(
                  backgroundColor: lightScheme.surface,
                  primaryColor: lightScheme.primary,
                  onPrimary: lightScheme.onPrimary,
                  onSurface: lightScheme.onSurface,
                  // 应用其他颜色...
                )
              : ColorScheme.fromSwatch(
                  primarySwatch: darkScheme.primary,
                ).copyWith(
                  backgroundColor: darkScheme.surface,
                  primaryColor: darkScheme.primary,
                  onPrimary: darkScheme.onPrimary,
                  onSurface: darkScheme.onSurface,
                  // 应用其他颜色...
                ),
        );
      },
      themedWidgetBuilder: (BuildContext context, ThemeData theme, Widget? child) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: theme,
          home: MyHomePage(),
        );
      },
    );
  }
}

3. 创建主页面

创建一个简单的页面来展示主题效果。

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Dynamic Theme Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You are in ${Theme.of(context).brightness == Brightness.light ? 'Light' : 'Dark'} mode',
              style: TextStyle(color: theme.colorScheme.onSurface),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 切换主题(这里只是一个示例,实际应用中可能需要持久化用户的选择)
                DynamicTheme.of(context).setBrightness(
                  Theme.of(context).brightness == Brightness.light
                      ? Brightness.dark
                      : Brightness.light,
                );
              },
              child: Text(
                'Switch Theme',
                style: TextStyle(color: theme.colorScheme.onPrimary),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

4. 运行应用

现在,你可以运行你的Flutter应用,并看到根据系统主题自动调整的主题颜色。此外,点击按钮可以手动切换亮模式和暗模式。

这个示例展示了如何使用dynamic_color_theme插件来为你的Flutter应用实现动态主题颜色切换。你可以根据自己的需求进一步自定义和扩展这个示例。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!