#
前言
主题切换功能是现代应用中提升用户体验的重要特性。用户可以根据个人喜好和使用环境选择不同的主题风格,如浅色主题、深色主题或跟随系统设置。对于笔记应用来说,合适的主题不仅能够保护用户视力,还能提供更舒适的阅读和编辑体验。本文将详细介绍如何在Flutter和OpenHarmony平台上实现完善的主题切换功能,包括主题定义、切换逻辑和持久化存储。
Flutter主题定义
Flutter通过ThemeData定义应用的主题样式。
dart
class AppThemes {
static final ThemeData lightTheme = ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Colors.white,
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
elevation: 0,
),
);
}
ThemeData是Flutter中定义主题的核心类,它包含了应用中几乎所有组件的默认样式。brightness设置整体亮度模式,primarySwatch定义主色调,scaffoldBackgroundColor设置页面背景色。appBarTheme专门配置AppBar的样式,包括背景色、前景色和阴影高度。将主题定义为静态常量便于在应用中统一引用和管理。
dart
static final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Color(0xFF121212),
appBarTheme: AppBarTheme(
backgroundColor: Color(0xFF1E1E1E),
foregroundColor: Colors.white,
elevation: 0,
),
cardColor: Color(0xFF1E1E1E),
dividerColor: Color(0xFF2C2C2C),
);
深色主题需要仔细选择颜色值以确保良好的可读性和视觉舒适度。scaffoldBackgroundColor使用深灰色而非纯黑色,这是Material Design推荐的做法,可以减少视觉疲劳。cardColor和dividerColor等属性需要与背景色协调,形成层次分明的视觉效果。深色主题在夜间使用时可以有效减少屏幕亮度对眼睛的刺激。
主题状态管理
使用Provider或其他状态管理方案来管理主题状态。
dart
class ThemeProvider extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.system;
ThemeMode get themeMode => _themeMode;
void setThemeMode(ThemeMode mode) {
_themeMode = mode;
_saveThemePreference(mode);
notifyListeners();
}
Future<void> _saveThemePreference(ThemeMode mode) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('themeMode', mode.toString());
}
}
ThemeProvider继承ChangeNotifier,这是Flutter中实现响应式状态管理的基础类。_themeMode存储当前的主题模式,支持light、dark和system三种模式。setThemeMode方法更新主题模式,同时将设置保存到SharedPreferences中实现持久化,最后调用notifyListeners通知所有监听者更新UI。这种设计使得主题切换可以即时生效,并且在应用重启后保持用户的选择。
dart
Future<void> loadThemePreference() async {
final prefs = await SharedPreferences.getInstance();
final savedMode = prefs.getString('themeMode');
if (savedMode != null) {
if (savedMode.contains('light')) {
_themeMode = ThemeMode.light;
} else if (savedMode.contains('dark')) {
_themeMode = ThemeMode.dark;
} else {
_themeMode = ThemeMode.system;
}
notifyListeners();
}
}
loadThemePreference方法在应用启动时调用,从SharedPreferences读取保存的主题设置。通过字符串匹配来解析ThemeMode枚举值,这种方式简单可靠。加载完成后调用notifyListeners确保UI使用正确的主题。这个方法通常在应用初始化阶段调用,确保用户看到的第一个界面就是正确的主题。
OpenHarmony主题实现
OpenHarmony通过资源文件和状态管理实现主题切换。
typescript
interface ThemeColors {
primary: string
background: string
surface: string
textPrimary: string
textSecondary: string
divider: string
}
const LightTheme: ThemeColors = {
primary: '#1890FF',
background: '#FFFFFF',
surface: '#F5F5F5',
textPrimary: '#333333',
textSecondary: '#666666',
divider: '#EEEEEE'
}
const DarkTheme: ThemeColors = {
primary: '#1890FF',
background: '#121212',
surface: '#1E1E1E',
textPrimary: '#FFFFFF',
textSecondary: '#AAAAAA',
divider: '#2C2C2C'
}
OpenHarmony中可以通过定义主题颜色接口来管理主题样式。ThemeColors接口定义了主题中需要的各种颜色,包括主色、背景色、表面色、文字颜色和分隔线颜色。LightTheme和DarkTheme分别定义浅色和深色主题的具体颜色值。这种结构化的定义方式使得主题管理更加清晰,添加新的颜色属性也很方便。
typescript
@Observed
class ThemeManager {
currentTheme: ThemeColors = LightTheme
isDarkMode: boolean = false
toggleTheme() {
this.isDarkMode = !this.isDarkMode
this.currentTheme = this.isDarkMode ? DarkTheme : LightTheme
this.saveThemePreference()
}
async saveThemePreference() {
let pref = await preferences.getPreferences(getContext(), 'settings')
await pref.put('isDarkMode', this.isDarkMode)
await pref.flush()
}
}
ThemeManager类使用@Observed装饰器使其成为可观察对象,当属性变化时会自动触发UI更新。toggleTheme方法切换主题模式,同时更新currentTheme和isDarkMode属性。saveThemePreference方法将主题设置保存到Preferences中,确保应用重启后能够恢复用户的选择。这种集中管理主题状态的方式使得主题切换逻辑清晰可控。
主题切换界面
提供直观的主题切换界面让用户选择偏好的主题。
dart
class ThemeSettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
return Column(
children: [
RadioListTile<ThemeMode>(
title: Text('浅色模式'),
value: ThemeMode.light,
groupValue: themeProvider.themeMode,
onChanged: (mode) => themeProvider.setThemeMode(mode!),
),
RadioListTile<ThemeMode>(
title: Text('深色模式'),
value: ThemeMode.dark,
groupValue: themeProvider.themeMode,
onChanged: (mode) => themeProvider.setThemeMode(mode!),
),
RadioListTile<ThemeMode>(
title: Text('跟随系统'),
value: ThemeMode.system,
groupValue: themeProvider.themeMode,
onChanged: (mode) => themeProvider.setThemeMode(mode!),
),
],
);
},
);
}
}
主题设置页面使用Consumer监听ThemeProvider的变化。RadioListTile提供了单选列表项的标准样式,非常适合主题选择场景。三个选项分别对应浅色模式、深色模式和跟随系统。groupValue绑定当前选中的主题模式,onChanged回调在用户选择时更新主题。跟随系统选项让应用能够自动适应系统的深色模式设置,这是现代应用的标准功能。
OpenHarmony主题设置
typescript
@Entry
@Component
struct ThemeSettingsPage {
@StorageLink('themeManager') themeManager: ThemeManager = new ThemeManager()
build() {
Column() {
Text('主题设置')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
Row() {
Text('深色模式')
.fontSize(16)
Blank()
Toggle({ type: ToggleType.Switch, isOn: this.themeManager.isDarkMode })
.onChange((isOn: boolean) => {
this.themeManager.toggleTheme()
})
}
.width('100%')
.padding(15)
.backgroundColor(this.themeManager.currentTheme.surface)
.borderRadius(8)
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor(this.themeManager.currentTheme.background)
}
}
OpenHarmony的主题设置页面使用@StorageLink装饰器连接全局的ThemeManager实例。Toggle组件提供开关样式的交互,isOn属性绑定当前的深色模式状态。onChange回调在用户切换开关时调用toggleTheme方法。页面的背景色和组件颜色都从currentTheme中获取,确保主题切换后界面能够即时更新。这种数据驱动的方式使得主题切换的实现非常简洁。
应用主题配置
在应用入口配置主题以使其全局生效。
dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
return MaterialApp(
theme: AppThemes.lightTheme,
darkTheme: AppThemes.darkTheme,
themeMode: themeProvider.themeMode,
home: HomePage(),
);
},
);
}
}
MaterialApp的theme属性设置浅色主题,darkTheme设置深色主题,themeMode控制使用哪个主题。当themeMode为ThemeMode.system时,应用会根据系统设置自动选择主题。Consumer确保当ThemeProvider的状态变化时,MaterialApp会重新构建并应用新的主题。这种配置方式使得主题切换对整个应用生效,所有页面都会使用统一的主题样式。
总结
主题切换功能是提升用户体验的重要特性,Flutter和OpenHarmony都提供了完善的主题支持。开发者需要合理定义主题样式、实现状态管理和持久化存储,才能为用户提供流畅的主题切换体验。深色模式不仅是视觉偏好,更是保护用户视力的重要功能,值得每个应用认真实现。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net