Flutter主题管理插件x_theme_provider的使用

Flutter主题管理插件x_theme_provider的使用

为什么使用ThemeProvider?

  • MaterialAppCupertinoApp无缝集成。
  • 轻松实现多主题管理。
  • 简化主题切换操作。
  • 提供对暗色模式、亮色模式、系统模式、下一个主题、上一个主题和切换主题的全面控制。
  • 可以持久化所选的主题。

演示: Theme Provider

使用方法

将你的XApp包裹在ThemeProvider中:

class YourApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ThemeProvider(
      theme: YourMaterialAppTheme(), // 或者 DefaultMaterialAppTheme
      builder: (theme) => MaterialApp(
        title: '您的应用标题',
        theme: theme,
        home: YourHomePage(),
      ),
    );
  }
}

ThemeProvider处理了MaterialApp中的darkThemethemeMode

切换主题

ThemeProvider.of(context).dark(); // 切换到暗色主题

ThemeProvider.of(context).light(); // 切换到亮色主题

ThemeProvider.of(context).system(); // 切换到系统主题

ThemeProvider.of(context).toggle(); // 切换当前主题

ThemeProvider.of(context).next(); // 切换到下一个主题

ThemeProvider.of(context).previous(); // 切换到上一个主题

ThemeProvider.of(context).index = themeIndex; // 设置主题索引

创建自定义主题

class YourMaterialAppTheme extends AppTheme<ThemeData> {
  YourMaterialAppTheme() : super(light, dark);

  final static ThemeData light = ThemeData(
    useMaterial3: true,
    brightness: Brightness.light,
    colorSchemeSeed: Colors.purple,
  );

  final static ThemeData dark = ThemeData(
    useMaterial3: true,
    brightness: Brightness.dark,
    colorSchemeSeed: Colors.purple,
  );
}

使用CupertinoApp

只需使用DefaultCupertinoTheme或自定义主题:

class YourApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ThemeProvider(
      theme: YourCupertinoAppTheme(),
      builder: (theme) => CupertinoApp(
        title: '您的应用标题',
        theme: theme,
        home: YourHomePage(),
      ),
    );
  }
}

监听主题变化

ThemeProvider.of(context).changeNotifier.addListener(() {
  // 执行您的操作,或者
  // 持久化状态如 pref.setX(key, ThemeProvider.of(context).jsonString)
});

或者通过UI监听变化:

ValueListenableBuilder(
  valueListenable: ThemeProvider.of(context).changeNotifier,
  ...
);

更多功能

// 获取当前主题?
Theme.of(context);

// 获取当前主题模式?
ThemeProvider.of(context).mode;

// 获取或设置当前主题索引?
ThemeProvider.of(context).index;

// 持久化能力?
ThemeProvider.of(context).jsonString;
ThemeProvider(
  init: jsonString,
  builder: ...
);

// 多主题?
ThemeProvider(
  themes: YourThemesList,
  builder: ...
);
// 并调用 next 或 previous 来切换主题。

喜欢Cross Theme Provider?

表达您的喜爱,通过给仓库点星,或者您可以:

Buy Me A Coffee

未来计划

  • 下载并安装主题!

示例代码

import 'package:flutter/material.dart';
import 'package:example/src/cupertino_app.dart';
import 'package:x_theme_provider/theme_provider.dart';
import 'package:example/src/my_material_themes.dart';

void main() => runApp(const MyMaterialApp());

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return ThemeProvider(
      themes: themes,
      builder: (theme) => MaterialApp(
        title: 'Flutter Demo',
        theme: theme,
        home: const MyHomePage(title: 'Flutter Material Demo'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text('${widget.title} - ${ThemeProvider.of(context).mode}'),
      ),
      body: buildBody(context, _buildButton, _buildAppSwitch, themes),
      floatingActionButton: FloatingActionButton(
        onPressed: ThemeProvider.of(context).toggle,
        tooltip: '切换主题',
        child: const Icon(Icons.contrast),
      ),
    );
  }

  Widget _buildButton(VoidCallback? onPressed, IconData icon, String label) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ElevatedButton.icon(
        onPressed: onPressed,
        icon: Icon(icon),
        label: Text(label),
      ),
    );
  }

  Widget _buildAppSwitch(BuildContext context, BtnBuilder btnBuilder) {
    return btnBuilder(
      () => Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => const MyCupertinoApp()),
      ),
      Icons.apple,
      'Cupertino',
    );
  }
}

typedef BtnBuilder = Widget Function(VoidCallback? onPressed, IconData icon, String label);

Widget buildBody(
  BuildContext context,
  BtnBuilder btnBuilder,
  Function(BuildContext context, BtnBuilder builder) buildAppSwitch,
  List<AppTheme> themes,
) {
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 40.0),
    child: SingleChildScrollView(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Wrap(
              alignment: WrapAlignment.center,
              children: buildFeatures(context, btnBuilder),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 40.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  buildAppSwitch(context, btnBuilder),
                ],
              ),
            ),
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: buildThemes(context, btnBuilder, themes),
            ),
          ],
        ),
      ),
    ),
  );
}

List<Widget> buildFeatures(BuildContext context, BtnBuilder btnBuilder) {
  final ThemeService service = ThemeProvider.of(context);

  return [
    btnBuilder(service.light, Icons.light_mode, 'light'),
    btnBuilder(service.dark, Icons.dark_mode, 'dark'),
    btnBuilder(service.system, Icons.settings, 'system'),
    btnBuilder(service.toggle, service.isDark ? Icons.toggle_off : Icons.toggle_on, 'toggle'),
  ];
}

List<Widget> buildThemes(BuildContext context, BtnBuilder btnBuilder, List<AppTheme> themes) {
  final ThemeService service = ThemeProvider.of(context);

  return [
    Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        btnBuilder(service.previous, Icons.skip_previous, 'previous'),
        btnBuilder(service.next, Icons.skip_next, 'next'),
      ],
    ),
    const SizedBox(height: 50,),
    Column(
      children: themes.map((theme) => btnBuilder(
        () => ThemeProvider.of(context).index = themes.indexOf(theme),
        (themes.indexOf(theme) == ThemeProvider.of(context).index)
          ? Icons.keyboard_double_arrow_right
          : Icons.keyboard_arrow_right_outlined,
        'Theme ${themes.indexOf(theme)} - ${theme.name}',
      )).toList(),
    ),
  ];
}

更多关于Flutter主题管理插件x_theme_provider的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


x_theme_provider 是一个用于 Flutter 应用主题管理的插件,它简化了主题切换和管理的流程。通过这个插件,你可以轻松地在应用中进行主题的切换,并且支持动态主题更新。

安装

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

dependencies:
  flutter:
    sdk: flutter
  x_theme_provider: ^latest_version

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

基本用法

  1. 定义主题

    你可以定义多个主题,例如 lightThemedarkTheme

    import 'package:flutter/material.dart';
    
    final ThemeData lightTheme = ThemeData(
      brightness: Brightness.light,
      primaryColor: Colors.blue,
      accentColor: Colors.blueAccent,
    );
    
    final ThemeData darkTheme = ThemeData(
      brightness: Brightness.dark,
      primaryColor: Colors.indigo,
      accentColor: Colors.indigoAccent,
    );
    
  2. 初始化主题提供者

    在应用的入口处,使用 XThemeProvider 来初始化主题提供者,并设置默认主题:

    import 'package:flutter/material.dart';
    import 'package:x_theme_provider/x_theme_provider.dart';
    
    void main() {
      runApp(
        XThemeProvider(
          defaultTheme: lightTheme,
          child: MyApp(),
        ),
      );
    }
    
  3. 在应用中使用主题

    在应用的任何地方,你可以通过 XThemeProvider.of(context) 来获取当前的主题,并将其应用到 MaterialApp 或其他组件中:

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final theme = XThemeProvider.of(context);
    
        return MaterialApp(
          theme: theme,
          home: HomeScreen(),
        );
      }
    }
    
  4. 切换主题

    你可以在应用的任何地方通过 XThemeProvider.updateTheme 方法来切换主题:

    class HomeScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Theme Provider Example'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    XThemeProvider.updateTheme(context, lightTheme);
                  },
                  child: Text('Light Theme'),
                ),
                ElevatedButton(
                  onPressed: () {
                    XThemeProvider.updateTheme(context, darkTheme);
                  },
                  child: Text('Dark Theme'),
                ),
              ],
            ),
          ),
        );
      }
    }
回到顶部