Flutter主题切换插件theme_patrol的使用

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

Flutter主题切换插件theme_patrol的使用

theme_patrol 是一个强大的Flutter插件,用于管理应用程序的主题切换。它支持在不同主题模式(如亮色/暗色)之间切换,并且可以轻松地在多个预定义的主题之间切换。

特性

  • 在亮色/暗色模式之间切换
  • 切换多个主题
  • 覆盖当前主题颜色

使用方法

基本用法

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemePatrol(
      initialMode: ThemeMode.system,
      light: ThemeData(
        brightness: Brightness.light,
        colorSchemeSeed: Colors.purple,
      ),
      dark: ThemeData(
        brightness: Brightness.dark,
        colorSchemeSeed: Colors.purple,
        toggleableActiveColor: Colors.purple,
      ),
      builder: (context, theme, child) {
        return MaterialApp(
          title: 'ThemePatrol',
          theme: theme.data,
          darkTheme: theme.darkData,
          themeMode: theme.mode,
          home: HomePage(),
        );
      },
    );
  }
}

消费者模式

ThemeController theme = ThemePatrol.of(context);

ThemeConsumer(
  builder: (context, theme, child) {
    return Container();
  },
);

详细配置

ThemeProvider(
  controller: ThemeController(
    initialMode: ThemeMode.system,
    light: ThemeData(
      brightness: Brightness.light,
      colorSchemeSeed: Colors.purple,
    ),
    // 其他配置...
  ),
  child: ThemeConsumer(
    builder: (context, theme, child) {
      return MaterialApp(
        title: 'ThemePatrol',
        theme: theme.data,
        darkTheme: theme.darkData,
        themeMode: theme.mode,
        home: HomePage(),
      );
    },
  ),
);

Provider 集成

import 'package:provider/provider.dart';

ChangeNotifierProvider(
  create: (_) => ThemeController(
    initialMode: ThemeMode.system,
    light: ThemeData(
      brightness: Brightness.light,
      colorSchemeSeed: Colors.purple,
    ),
    // 其他配置...
  ),
  child: ...,
);

// 获取主题控制器
ThemeController theme = Provider.of<ThemeController>(context, listen: true);
ThemeController theme = context.watch<ThemeController>();
ThemeController theme = context.read<ThemeController>();
ThemeMode mode = context.select((ThemeController theme) => theme.mode);

使用场景

仅在亮色/暗色模式之间切换

ThemePatrol(
  initialMode: ThemeMode.system,
  light: ThemeData(
    brightness: Brightness.light,
    colorSchemeSeed: Colors.purple,
  ),
  dark: ThemeData(
    brightness: Brightness.dark,
    colorSchemeSeed: Colors.purple,
    toggleableActiveColor: Colors.purple,
  ),
  builder: (context, theme, child) {
    return MaterialApp(
      title: 'ThemePatrol',
      theme: theme.data,
      darkTheme: theme.darkData,
      themeMode: theme.mode,
      home: Scaffold(
        appBar: AppBar(
          title: Text(ThemePatrol.of(context).mode.toString()),
          actions: [
            ThemeConsumer(
              builder: (context, theme, child) {
                return Switch(
                  value: theme.isDarkMode,
                  onChanged: (selected) {
                    if (selected) {
                      theme.toDarkMode();
                    } else {
                      theme.toLightMode();
                    }
                  },
                );
              },
            ),
          ],
        ),
      ),
    );
  },
);

多个主题,无暗色模式

ThemePatrol(
  initialTheme: 'amber',
  themes: {
    'purple': ThemeConfig.fromColor(Colors.purple),
    'pink': ThemeConfig.fromColor(Colors.pink),
    'amber': ThemeConfig.fromColor(Colors.amber),
    'elegant': ThemeConfig(data: ThemeData()),
  },
  builder: (context, theme, child) {
    return MaterialApp(
      title: 'ThemePatrol',
      theme: theme.data,
      home: Scaffold(
        appBar: AppBar(
          title: Text(ThemePatrol.of(context).selected),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ThemeConsumer(
                builder: (context, theme, _) {
                  return Wrap(
                    spacing: 5,
                    children: theme.availableEntries
                        .map((e) => ActionChip(
                              label: Text(e.key),
                              onPressed: () => theme.select(e.key),
                              avatar: CircleAvatar(
                                backgroundColor:
                                    e.value.colorSchemeOf(context).primary,
                              ),
                            ))
                        .toList(),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  },
);

多个主题,带暗色模式

ThemePatrol(
  initialTheme: 'amber',
  initialMode: ThemeMode.system,
  themes: {
    'purple': ThemeConfig.fromColor(Colors.purple),
    'pink': ThemeConfig.fromColor(Colors.pink),
    'amber': ThemeConfig.fromColor(Colors.amber),
    'basic': ThemeConfig(data: ThemeData()),
    'pro': ThemeConfig(data: ThemeData(), dark: ThemeData()),
    'premium': ThemeConfig(light: ThemeData(), dark: ThemeData()),
  },
  builder: (context, theme, _) {
    return MaterialApp(
      title: 'ThemePatrol',
      theme: theme.data,
      darkTheme: theme.darkData,
      themeMode: theme.mode,
      home: Scaffold(
        appBar: AppBar(
          title: Text(ThemePatrol.of(context).selected),
          actions: [
            ThemeConsumer(
              builder: (context, theme, _) {
                return Switch(
                  value: theme.isDarkMode,
                  onChanged: (selected) {
                    if (selected) {
                      theme.toDarkMode();
                    } else {
                      theme.toLightMode();
                    }
                  },
                );
              },
            ),
          ],
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ThemeConsumer(
                builder: (context, theme, _) {
                  return Wrap(
                    spacing: 5,
                    children: theme.available.entries
                        .map((e) => ActionChip(
                              label: Text(e.key),
                              onPressed: () => theme.select(e.key),
                              avatar: CircleAvatar(
                                backgroundColor:
                                    e.value.colorSchemeOf(context).primary,
                              ),
                            ))
                        .toList(),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  },
);

完整示例 Demo

以下是一个完整的示例,展示了如何使用 theme_patrol 插件来实现主题切换功能:

import 'dart:developer';

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ThemePatrol(
      onAvailableChanged: (_) => log('available themes changed'),
      onThemeChanged: (theme) => log('theme changed to ${theme.selected}'),
      onModeChanged: (theme) => log('theme mode changed to ${theme.mode.name}'),
      onColorChanged: (theme) =>
          log('theme color changed to ${theme.color.toString()}'),
      onChanged: (theme) => log('value changed'),
      themes: {
        'basic': ThemeConfig.fromColor(Colors.purple),
        'pro': ThemeConfig.fromColor(Colors.red),
        'premium': ThemeConfig.fromColor(Colors.amber),
      },
      light: ThemeData.light(),
      dark: ThemeData.dark(),
      builder: (context, theme, _) {
        return MaterialApp(
          title: 'ThemePatrol Example',
          theme: theme.data,
          darkTheme: theme.darkData,
          themeMode: theme.mode,
          home: const MyHomePage(title: 'ThemePatrol Example'),
          builder: theme.bootstrap(),
        );
      },
    );
  }
}

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

  final String title;

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

class MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(0, 45, 0, 25),
                child: Center(
                  child: Text(
                    'ThemePatrol',
                    style: TextStyle(
                      fontSize: 36,
                      fontWeight: FontWeight.bold,
                      letterSpacing: -2,
                    ),
                  ),
                ),
              ),
              ThemeConsumer(
                builder: (context, theme, _) {
                  return Column(
                    children: [
                      ElevatedButton.icon(
                        onPressed: () => theme.toggleMode(),
                        icon: AnimatedSwitcher(
                          duration: const Duration(milliseconds: 200),
                          child: Icon(
                            theme.modeIcon,
                            key: ValueKey(theme.mode),
                          ),
                        ),
                        label: Text('${theme.mode.name.toUpperCase()} MODE'),
                      ),
                      const SizedBox(height: 10),
                      OutlinedButton(
                        onPressed: () => theme.resetMode(),
                        child: const Text('Reset to Initial Mode'),
                      ),
                    ],
                  );
                },
              ),
              const SizedBox(height: 30),
              ThemeConsumer(
                builder: (context, theme, _) {
                  return Wrap(
                    spacing: 5,
                    children: theme.availableEntries
                        .map((e) => FilterChip(
                              label: Text(e.key),
                              onSelected: (_) => theme.select(e.key),
                              selected: theme.selected == e.key,
                              checkmarkColor: Colors.white,
                              avatar: CircleAvatar(
                                backgroundColor:
                                    e.value.colorSchemeOf(context).primary,
                              ),
                            ))
                        .toList(),
                  );
                },
              ),
              const SizedBox(height: 20),
              Wrap(
                spacing: 5,
                children: [
                  TextButton(
                    onPressed: () => ThemePatrol.of(context).selectPrev(),
                    child: const Text('Prev Theme'),
                  ),
                  ElevatedButton(
                    onPressed: () => ThemeProvider.of(context).resetTheme(),
                    child: const Text('Reset to Initial Theme'),
                  ),
                  TextButton(
                    onPressed: () => ThemeProvider.of(context).selectNext(),
                    child: const Text('Next Theme'),
                  ),
                ],
              ),
              const SizedBox(height: 10),
              OutlinedButton(
                onPressed: () => ThemePatrol.of(context).selectRandom(),
                child: const Text('Random Theme'),
              ),
              const SizedBox(height: 30),
              const Text(
                'Override Theme Color',
                style: TextStyle(fontWeight: FontWeight.w400),
              ),
              const SizedBox(height: 10),
              ThemeConsumer(builder: (context, theme, _) {
                return Container(
                  width: 200,
                  alignment: Alignment.center,
                  child: GridView.builder(
                    shrinkWrap: true,
                    itemCount: Colors.primaries.length,
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      mainAxisSpacing: 2,
                      crossAxisSpacing: 2,
                      crossAxisCount: 6,
                    ),
                    itemBuilder: (_, i) {
                      final color = Colors.primaries[i];
                      return Card(
                        color: color,
                        clipBehavior: Clip.antiAlias,
                        child: InkWell(
                          onTap: () => theme.toColor(color),
                          child: AnimatedCheckmark(
                            weight: 4,
                            color: Colors.white70,
                            active: color == theme.color,
                          ),
                        ),
                      );
                    },
                  ),
                );
              }),
              const SizedBox(height: 10),
              TextButton(
                onPressed: () => ThemePatrol.of(context).resetColor(),
                child: const Text('Reset Color to Theme Color'),
              ),
              const SizedBox(height: 30),
              ElevatedButton(
                onPressed: () => ThemePatrol.of(context).reset(),
                child: const Text('Reset All to Initial Values'),
              )
            ],
          ),
        ),
      ),
    );
  }
}

通过这个完整的示例,你可以了解如何使用 theme_patrol 插件来实现丰富的主题切换功能。


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

1 回复

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


当然,下面是如何在Flutter应用中使用theme_patrol插件来实现主题切换的示例代码。theme_patrol是一个用于Flutter的插件,它简化了主题切换的实现。假设你已经将theme_patrol添加到你的pubspec.yaml文件中并运行了flutter pub get

1. 添加依赖

首先,确保你的pubspec.yaml文件中包含theme_patrol依赖:

dependencies:
  flutter:
    sdk: flutter
  theme_patrol: ^最新版本号  # 替换为最新版本号

2. 设置主题数据

在你的main.dart文件中,定义两个主题(例如,亮色主题和暗色主题):

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemePatrol(
      // 初始主题
      initialThemeMode: ThemeMode.system, // 可以是 ThemeMode.light, ThemeMode.dark, 或 ThemeMode.system
      themes: {
        ThemeMode.light: ThemeData(
          brightness: Brightness.light,
          primarySwatch: Colors.blue,
          // 其他主题设置
        ),
        ThemeMode.dark: ThemeData(
          brightness: Brightness.dark,
          primarySwatch: Colors.deepPurple,
          // 其他主题设置
        ),
      },
      builder: (context, theme) {
        return MaterialApp(
          title: 'Flutter Theme Patrol Demo',
          theme: theme,
          home: MyHomePage(),
        );
      },
    );
  }
}

3. 创建主题切换按钮

在你的MyHomePage中,添加一个按钮来切换主题:

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final ThemePatrolController themePatrolController = ThemePatrol.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Theme Patrol Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Current Theme Mode: ${themePatrolController.themeMode == ThemeMode.light ? 'Light' : 'Dark'}',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                themePatrolController.setThemeMode(
                  themePatrolController.themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light,
                );
              },
              child: Text('Switch Theme'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 完整代码

以下是完整的main.dart代码,包含上述所有部分:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemePatrol(
      initialThemeMode: ThemeMode.system,
      themes: {
        ThemeMode.light: ThemeData(
          brightness: Brightness.light,
          primarySwatch: Colors.blue,
        ),
        ThemeMode.dark: ThemeData(
          brightness: Brightness.dark,
          primarySwatch: Colors.deepPurple,
        ),
      },
      builder: (context, theme) {
        return MaterialApp(
          title: 'Flutter Theme Patrol Demo',
          theme: theme,
          home: MyHomePage(),
        );
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final ThemePatrolController themePatrolController = ThemePatrol.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Theme Patrol Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Current Theme Mode: ${themePatrolController.themeMode == ThemeMode.light ? 'Light' : 'Dark'}',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                themePatrolController.setThemeMode(
                  themePatrolController.themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light,
                );
              },
              child: Text('Switch Theme'),
            ),
          ],
        ),
      ),
    );
  }
}

这个示例展示了如何使用theme_patrol插件在Flutter应用中实现主题切换功能。你可以根据需要进一步自定义和扩展这些代码。

回到顶部