Flutter主题配置插件theme_config的使用
Flutter主题配置插件theme_config的使用
ThemeConfig 使得在平台主题改变时切换状态栏和导航栏样式变得简单。




特性
- 设置系统栏的亮色和暗色样式
- 自动更新系统栏当平台亮度变化时
- 监听主题模式变化
开始使用
创建一个独立定义每个样式的主题配置文件:
final themeProfile = ThemeProfile(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
overlayStyle: SystemUiOverlayStyle.light,
darkOverlayStyle: SystemUiOverlayStyle.dark,
);
或者基于颜色方案:
final themeProfile = ThemeProfile.fromColorScheme(
colorScheme: ColorScheme.light(),
darkColorScheme: ColorScheme.dark(),
theme: (colorScheme) => ThemeData.from(colorScheme: colorScheme),
overlayStyle: (colorScheme) => SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
systemNavigationBarColor: Colors.black,
systemNavigationBarIconBrightness: Brightness.light,
),
);
初始化 ThemeConfig 以便它可以保存和加载主题模式偏好设置:
Future<void> main() async {
...
await ThemeConfig.init(themeProfile);
runApp(MyApp());
}
将 MaterialApp
包裹在 ThemeBuilder
中,以便它可以监听平台亮度和主题模式的变化并相应地更改系统栏:
ThemeBuilder(
builder: (theme) => MaterialApp(
...
theme: theme.light,
darkTheme: theme.dark,
themeMode: theme.mode,
),
)
使用方法
在项目的任何位置访问应用程序的亮度和主题模式:
final brightness = ThemeConfig.brightness;
final themeMode = ThemeConfig.themeMode;
在不同主题模式之间切换:
ThemeConfig.setThemeMode(ThemeMode.light);
ThemeConfig.setThemeMode(ThemeMode.dark);
ThemeConfig.setThemeMode(ThemeMode.system);
例如使用 RadioListTile
:
Widget myRadioListTile(ThemeMode themeMode) {
return RadioListTile<ThemeMode>(
title: Text(themeMode.name),
value: themeMode,
groupValue: ThemeConfig.themeMode,
onChanged: (mode) => setState(() => ThemeConfig.setThemeMode(mode)),
);
}
Column(children: ThemeMode.values.map(myRadioListTile).toList())
动态重新定义覆盖样式:
ThemeConfig.setOverlayStyle(newOverlayStyle);
ThemeConfig.setDarkOverlayStyle(newDarkOverlayStyle);
更改当前覆盖样式:
ThemeConfig.setCustomOverlayStyle(customOverlayStyle);
移除当前覆盖样式:
ThemeConfig.removeCustomOverlayStyle();
临时更改特定页面上的亮色和/或暗色覆盖样式:
OverlayStyle(
light: newOverlayStyle,
dark: newDarkOverlayStyle,
child: ...
)
或者使用自定义覆盖样式:
OverlayStyle.custom(
style: customOverlayStyle,
child: ...
)
为了让此组件工作,你还需要将我们的观察者添加到 MaterialApp
:
MaterialApp(
...
navigatorObservers: [ThemeConfig.routeObserver],
)
其他信息
如果您发现任何不在 issues 中的错误,请提交一个新的问题。如果您愿意自己修复或增强某些功能,欢迎提交拉取请求。
完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:theme_config/theme_config.dart';
// 1. 创建一个主题配置文件
final themeProfile = ThemeProfile.fromColorScheme(
// 定义颜色方案
colorScheme: const ColorScheme.light(),
darkColorScheme: const ColorScheme.dark(),
// 定义主题
theme: (colorScheme) => ThemeData(
colorScheme: colorScheme,
scaffoldBackgroundColor: colorScheme.background,
appBarTheme: AppBarTheme(
elevation: 0,
color: colorScheme.background,
foregroundColor: colorScheme.onBackground,
),
),
// 定义覆盖样式
overlayStyle: (colorScheme) => SystemUiOverlayStyle(
// android
statusBarColor: Colors.transparent,
statusBarIconBrightness: colorScheme.brightness == Brightness.light ? Brightness.dark : Brightness.light,
systemNavigationBarColor: colorScheme.background,
systemNavigationBarIconBrightness: colorScheme.brightness == Brightness.light ? Brightness.dark : Brightness.light,
// ios
statusBarBrightness: colorScheme.brightness,
),
);
void main() async {
// 2. 初始化插件
await ThemeConfig.init(themeProfile);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
// 3. 将应用包裹在 ThemeBuilder 中
// 监听主题和亮度变化
return ThemeBuilder(
builder: (theme) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'ThemeConfig 示例',
home: const Example(),
// 4. 设置主题属性
theme: theme.light,
darkTheme: theme.dark,
themeMode: theme.mode,
// 如果计划使用 OverlayStyle 组件,请添加此行
navigatorObservers: [ThemeConfig.routeObserver],
);
},
);
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
[@override](/user/override)
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ThemeConfig 示例')),
body: SingleChildScrollView(
child: Column(
children: [
...ThemeMode.values.map(
(themeMode) => radioTile(themeMode, setState),
),
const SizedBox(height: 16),
OutlinedButton(
child: const Text('设置亮色覆盖样式'),
onPressed: () => ThemeConfig.setOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.yellow,
systemNavigationBarColor: Colors.yellow,
),
),
),
OutlinedButton(
child: const Text('设置暗色覆盖样式'),
onPressed: () => ThemeConfig.setDarkOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.deepPurple,
systemNavigationBarColor: Colors.deepPurple,
),
),
),
const SizedBox(height: 16),
OutlinedButton(
child: const Text('设置自定义覆盖样式'),
onPressed: () => ThemeConfig.setCustomOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.pink,
systemNavigationBarColor: Colors.pink,
),
),
),
OutlinedButton(
child: const Text('移除自定义覆盖样式'),
onPressed: () => ThemeConfig.removeCustomOverlayStyle(),
),
const SizedBox(height: 16),
OutlinedButton(
child: const Text('导航到亮色/暗色覆盖页面'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const OverlayPage()),
).then((_) => setState(() {})),
),
OutlinedButton(
child: const Text('导航到自定义覆盖页面'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const CustomOverlayPage()),
),
),
],
),
),
);
}
}
class OverlayPage extends StatefulWidget {
const OverlayPage({Key? key}) : super(key: key);
[@override](/user/override)
State<OverlayPage> createState() => _OverlayPageState();
}
class _OverlayPageState extends State<OverlayPage> {
[@override](/user/override)
Widget build(BuildContext context) {
return OverlayStyle(
light: const SystemUiOverlayStyle(
statusBarColor: Colors.orange,
systemNavigationBarColor: Colors.orange,
),
dark: const SystemUiOverlayStyle(
statusBarColor: Colors.blue,
systemNavigationBarColor: Colors.blue,
),
child: Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
...ThemeMode.values.map(
(themeMode) => radioTile(themeMode, setState),
),
OutlinedButton(
child: const Text('返回'),
onPressed: Navigator.of(context).pop,
),
],
),
),
),
),
);
}
}
class CustomOverlayPage extends StatelessWidget {
const CustomOverlayPage({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return OverlayStyle.custom(
style: const SystemUiOverlayStyle(
statusBarColor: Colors.green,
systemNavigationBarColor: Colors.green,
),
child: Scaffold(
body: Center(
child: OutlinedButton(
child: const Text('返回'),
onPressed: Navigator.of(context).pop,
),
),
),
);
}
}
Widget radioTile(
ThemeMode themeMode,
void Function(void Function()) setState,
) =>
RadioListTile<ThemeMode>(
title: Text(themeMode.name),
value: themeMode,
groupValue: ThemeConfig.themeMode,
onChanged: (mode) => setState(() => ThemeConfig.setThemeMode(mode!)),
);
更多关于Flutter主题配置插件theme_config的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter主题配置插件theme_config的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用theme_config
插件来配置主题的一个基本示例。theme_config
插件允许你动态地更改应用的主题,包括颜色、字体等。不过,需要注意的是,theme_config
并非Flutter官方插件,所以具体的使用方式可能会根据插件的版本和文档有所不同。这里我们假设插件的使用方式与常见的主题管理插件类似。
首先,你需要在你的pubspec.yaml
文件中添加theme_config
插件(注意:这里假设插件名为theme_config
,如果实际插件名称不同,请替换为实际名称):
dependencies:
flutter:
sdk: flutter
theme_config: ^x.y.z # 替换为实际的版本号
然后运行flutter pub get
来安装插件。
接下来,我们设置应用的主题。在lib
目录下创建一个新的Dart文件,比如theme_data.dart
,用于定义我们的主题数据:
// theme_data.dart
import 'package:flutter/material.dart';
final LightTheme = ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
);
final DarkTheme = ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blueGrey,
visualDensity: VisualDensity.adaptivePlatformDensity,
);
然后,在你的main.dart
文件中,使用theme_config
插件来管理主题:
// main.dart
import 'package:flutter/material.dart';
import 'package:theme_config/theme_config.dart'; // 假设插件提供这样的导入路径
import 'theme_data.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ThemeConfig(
initialTheme: LightTheme, // 设置初始主题
themes: {
'light': LightTheme,
'dark': DarkTheme,
},
builder: (context, theme) {
return MaterialApp(
title: 'Flutter Theme Config Demo',
theme: theme,
home: HomeScreen(),
);
},
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
final ThemeConfig themeConfig = ThemeConfig.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Theme Config Demo'),
actions: [
IconButton(
icon: Icon(themeConfig.currentThemeName == 'light' ? Icons.dark_mode : Icons.light_mode),
onPressed: () {
setState(() {
themeConfig.setThemeName(themeConfig.currentThemeName == 'light' ? 'dark' : 'light');
});
},
),
],
),
body: Center(
child: Text('Current Theme: ${themeConfig.currentThemeName}'),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 在
theme_data.dart
中定义了两个主题:LightTheme
和DarkTheme
。 - 在
main.dart
中使用ThemeConfig
包装了MaterialApp
,并设置了初始主题和可用的主题。 - 在
HomeScreen
中,通过ThemeConfig.of(context)
获取当前的ThemeConfig
实例,并在AppBar中添加了一个按钮来切换主题。
请注意,上述代码是基于假设的theme_config
插件的使用方式。实际使用时,请查阅该插件的官方文档以获取准确的API和用法。如果theme_config
插件不存在或API有所不同,你可能需要寻找其他类似功能的插件或手动实现主题管理功能。