Flutter动态主题切换插件dynamic_themes的使用

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

Flutter动态主题切换插件dynamic_themes的使用

dynamic_themes 是一个用于在Flutter应用中实现多主题动态切换的插件。它允许用户从多个预定义的主题中选择,并且能够在运行时动态地更新所选主题,同时支持跨应用重启持久化保存所选主题。

动态更改多个主题

该插件允许你为用户提供多个可选主题。主题可以在应用程序运行期间动态更新,并且会将选定的主题保存下来,在下次启动应用时自动恢复。

开始使用

请按照 官方安装指南 来添加依赖并配置你的项目。

使用方法

定义主题集合

你可以定义任意数量的主题,并为每个主题分配一个唯一的 int 类型ID。推荐创建一个包含静态常量整数的类来关联名称与ID值:

class AppThemes {
  static const int LightBlue = 0;
  static const int LightRed = 1;
  static const int Dark = 2;

  // 可以根据需要添加更多主题
}

final themeCollection = ThemeCollection(
    themes: {
        AppThemes.LightBlue: ThemeData(primarySwatch: Colors.blue),
        AppThemes.LightRed: ThemeData(primarySwatch: Colors.red),
        AppThemes.Dark: ThemeData.dark(),
    },
    fallbackTheme: ThemeData.light(), // 可选的默认主题
);

包装MaterialApp

接下来,用 DynamicTheme 小部件包装你的 MaterialApp

return DynamicTheme(
    themeCollection: themeCollection,
    defaultThemeId: AppThemes.LightBlue, // 可选,默认主题ID为0
    builder: (context, theme) {
        return MaterialApp(
            title: 'dynamic_themes example',
            theme: theme,
            home: HomePage(title: 'dynamic_themes example app'),
        );
    }
);

切换主题

在应用中的任何地方,只要拥有 BuildContext,就可以通过以下方式设置或切换主题:

DynamicTheme.of(context).setTheme(AppThemes.LightRed);

这将自动通过 shared_preferences 插件保存主题ID,确保下次启动应用时能够正确恢复主题。

获取当前主题信息

你可以像往常一样通过 Theme.of(context) 获取当前主题,也可以直接通过 DynamicTheme.of(context).theme 获取。若要获取当前主题的ID(例如用于构建UI选择器),可以调用:

final themeId = DynamicTheme.of(context).themeId;

示例代码

下面是一个完整的示例应用,演示了如何实现四个不同主题之间的切换功能:

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

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

/// 应用的主题。
/// 此类仅用于将可读名称与整数主题ID关联起来。
class AppThemes {
  static const int LightBlue = 0;
  static const int LightRed = 1;
  static const int DarkBlue = 2;
  static const int DarkRed = 3;

  static String toStr(int themeId) {
    switch (themeId) {
      case LightBlue:
        return "Light Blue";
      case LightRed:
        return "Light Red";
      case DarkBlue:
        return "Dark Blue";
      case DarkRed:
        return "Dark Red";
      default:
        return "Unknown";
    }
  }
}

class DynamicThemesExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final dark = ThemeData.dark();
    final darkButtonTheme = dark.buttonTheme.copyWith(buttonColor: Colors.grey[700]);
    final darkFABTheme = dark.floatingActionButtonTheme;

    final themeCollection = ThemeCollection(
      themes: {
        AppThemes.LightBlue: ThemeData(primarySwatch: Colors.blue),
        AppThemes.LightRed: ThemeData(primarySwatch: Colors.red),
        AppThemes.DarkBlue: dark.copyWith(
          accentColor: Colors.blue, 
          buttonTheme: darkButtonTheme,
          floatingActionButtonTheme: darkFABTheme.copyWith(backgroundColor: Colors.blue)),
        AppThemes.DarkRed: ThemeData.from(colorScheme: ColorScheme.dark(primary: Colors.red, secondary: Colors.red)),
      }
    );

    return DynamicTheme(
      themeCollection: themeCollection,
      defaultThemeId: AppThemes.LightBlue,
      builder: (context, theme) {
        return MaterialApp(
          title: 'dynamic_themes example',
          theme: theme,
          home: HomePage(title: 'dynamic_themes example app'),
        );
      }
    );
  }
}

class HomePage extends StatefulWidget {
  final String title;

  const HomePage({Key? key, required this.title}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int dropdownValue = 0;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    dropdownValue = DynamicTheme.of(context)!.themeId;
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(children: [
          Padding(
            padding: const EdgeInsets.only(top: 24, bottom: 12),
            child: Text('Select your theme here:'),
          ),
          DropdownButton(
            icon: Icon(Icons.arrow_downward),
            value: dropdownValue,
            items: [
              DropdownMenuItem(
                value: AppThemes.LightBlue,
                child: Text(AppThemes.toStr(AppThemes.LightBlue)),
              ),
              DropdownMenuItem(
                value: AppThemes.LightRed,
                child: Text(AppThemes.toStr(AppThemes.LightRed)),
              ),
              DropdownMenuItem(
                value: AppThemes.DarkBlue,
                child: Text(AppThemes.toStr(AppThemes.DarkBlue)),
              ),
              DropdownMenuItem(
                value: AppThemes.DarkRed,
                child: Text(AppThemes.toStr(AppThemes.DarkRed)),
              )
            ], 
            onChanged: (dynamic themeId) async {
              await DynamicTheme.of(context)!.setTheme(themeId);
              setState(() {
                dropdownValue = themeId;
              });
            }
          ),
          Container(
            margin: EdgeInsets.all(20),
            width: 100,
            height: 100,
            color: theme.primaryColor,
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  'Container in primary color and primary text theme', 
                  textAlign: TextAlign.center,
                  style: Theme.of(context).primaryTextTheme.bodyText2
                ),
              ),
            )
          ),
          Container(
            margin: EdgeInsets.all(20),
            width: 100,
            height: 100,
            color: theme.accentColor,
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  'Container in accent color and with accent text theme', 
                  textAlign: TextAlign.center,
                  style: Theme.of(context).accentTextTheme.bodyText2),
              )),
          ),
          ElevatedButton(
            onPressed: () {},
            child: Text('Elevated Button'),
          ),
        ],
        )
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
          BottomNavigationBarItem(icon: Icon(Icons.notifications), label: "Notifications"),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () { },
        child: Icon(Icons.add),
      ),
    );
  }
}

以上就是关于 dynamic_themes 插件的基本介绍和使用示例。如果你有任何问题或者建议,欢迎访问 GitHub Issues 提交反馈。


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

1 回复

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


当然,以下是如何在Flutter项目中使用dynamic_themes插件来实现动态主题切换的一个示例代码。dynamic_themes插件允许你在运行时更改应用程序的主题(如亮色主题和暗色主题)。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  dynamic_themes: ^1.0.0  # 请确保使用最新版本

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

2. 配置主题

lib目录下创建一个新的文件themes.dart,用于定义亮色和暗色主题:

import 'package:flutter/material.dart';

// 亮色主题
final lightTheme = ThemeData(
  brightness: Brightness.light,
  primaryColor: Colors.blue,
  accentColor: Colors.teal,
  backgroundColor: Colors.white,
  textTheme: TextTheme(
    bodyText1: TextStyle(color: Colors.black),
  ),
  // 其他主题配置...
);

// 暗色主题
final darkTheme = ThemeData(
  brightness: Brightness.dark,
  primaryColor: Colors.blueGrey,
  accentColor: Colors.lightBlueAccent,
  backgroundColor: Colors.grey[900],
  textTheme: TextTheme(
    bodyText1: TextStyle(color: Colors.white),
  ),
  // 其他主题配置...
);

// 主题列表
final List<ThemeData> themes = [lightTheme, darkTheme];

3. 设置应用

main.dart中,使用DynamicTheme插件来管理主题切换:

import 'package:flutter/material.dart';
import 'package:dynamic_themes/dynamic_themes.dart';
import 'themes.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DynamicTheme(
      defaultBrightness: Brightness.light, // 默认亮度
      themes: themes, // 主题列表
      themedWidgetBuilder: (context, theme) {
        return MaterialApp(
          title: 'Flutter Dynamic Theme Demo',
          theme: theme,
          home: HomeScreen(),
        );
      },
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  bool isDarkMode = false;

  void toggleTheme() {
    setState(() {
      isDarkMode = !isDarkMode;
      DynamicTheme.of(context).setBrightness(
        isDarkMode ? Brightness.dark : Brightness.light,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dynamic Theme Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Current Theme: ${isDarkMode ? 'Dark' : 'Light'}',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: toggleTheme,
              child: Text('Toggle Theme'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 运行应用

现在你可以运行你的Flutter应用,你应该能够看到一个带有主题切换按钮的页面。点击按钮将切换亮色和暗色主题。

这个示例展示了如何使用dynamic_themes插件来动态切换Flutter应用的主题。你可以根据需要进一步自定义和扩展主题配置。

回到顶部