Flutter for OpenHarmony 微动漫App实战:主题配置实现

Flutter for OpenHarmony 微动漫App实战:主题配置实现

通过网盘分享的文件:flutter1.zip

链接: https://pan.baidu.com/s/1jkLZ9mZXjNm0LgP6FTVRzw 提取码: 2t97

主题决定了 App 的视觉风格,包括颜色、字体、组件样式等。Flutter 的 ThemeData 提供了强大的主题配置能力,一处配置全 App 生效。

这篇文章会实现完整的主题配置,讲解 ThemeData 的各项配置、ColorScheme 颜色方案、Material 3 设计语言,以及如何设计一套协调的浅色和深色主题。


主题配置的意义

为什么要配置主题?

统一风格:所有组件使用相同的颜色和样式,视觉一致。

易于维护:修改主色只需要改一处,全 App 生效。

支持深色模式:定义两套主题,系统自动切换。

品牌识别:独特的配色让用户记住你的 App。


主题类的基础结构

dart 复制代码
import 'package:flutter/material.dart';

class AppTheme {
  static const Color primaryColor = Color(0xFFFF6B9D);
  static const Color secondaryColor = Color(0xFF9B59B6);
  static const Color accentColor = Color(0xFFFFB347);
  static const Color darkBg = Color(0xFF1A1A2E);
  static const Color darkCard = Color(0xFF16213E);

先定义常用颜色常量:

primaryColor 是主色,粉红色,用于按钮、选中状态等。

secondaryColor 是次色,紫色,用于渐变和强调。

accentColor 是点缀色,橙色,用于特殊元素。

darkBgdarkCard 是深色模式的背景色和卡片色。


颜色选择的原则

主色:代表品牌,要有辨识度,不能太刺眼。

次色:和主色搭配,用于渐变或次要元素。

点缀色:少量使用,吸引注意力。

背景色:浅色模式用浅灰而不是纯白,深色模式用深蓝而不是纯黑,更舒适。


浅色主题配置

dart 复制代码
static ThemeData lightTheme = ThemeData(
  useMaterial3: true,
  brightness: Brightness.light,
  primaryColor: primaryColor,
  colorScheme: ColorScheme.light(
    primary: primaryColor,
    secondary: secondaryColor,
    tertiary: accentColor,
    surface: Colors.white,
    background: const Color(0xFFF8F9FA),
  ),

useMaterial3: true 启用 Material 3 设计语言,组件样式更现代。

brightness: Brightness.light 告诉 Flutter 这是浅色主题。

ColorScheme 定义了一整套颜色,Flutter 组件会自动使用这些颜色。


ColorScheme 详解

dart 复制代码
ColorScheme.light(
  primary: primaryColor,      // 主色,按钮、选中状态
  secondary: secondaryColor,  // 次色,FAB、进度条
  tertiary: accentColor,      // 第三色,特殊元素
  surface: Colors.white,      // 表面色,卡片、对话框
  background: const Color(0xFFF8F9FA),  // 背景色
)

primary 是最重要的颜色,用于按钮、AppBar、选中状态等。

secondary 用于 FloatingActionButton、进度条等。

surface 是卡片、对话框等表面的颜色。

background 是页面背景色。


Scaffold 背景色

dart 复制代码
scaffoldBackgroundColor: const Color(0xFFF8F9FA),

scaffoldBackgroundColor 设置 Scaffold 的背景色。

用浅灰色(#F8F9FA)而不是纯白,看起来更柔和,也能和白色卡片区分开。


AppBar 主题

dart 复制代码
appBarTheme: const AppBarTheme(
  backgroundColor: Colors.white,
  foregroundColor: Colors.black87,
  elevation: 0,
  centerTitle: true,
),

backgroundColor 是 AppBar 背景色,浅色模式用白色。

foregroundColor 是标题和图标的颜色,用深灰色。

elevation: 0 去掉阴影,更扁平。

centerTitle: true 标题居中,这是很多 App 的常见设计。


Card 主题

dart 复制代码
cardTheme: CardTheme(
  elevation: 2,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),

elevation: 2 设置卡片阴影,轻微的阴影让卡片有层次感。

shape 设置卡片形状,16 像素的圆角让卡片看起来更圆润。


底部导航栏主题

dart 复制代码
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
  backgroundColor: Colors.white,
  selectedItemColor: primaryColor,
  unselectedItemColor: Colors.grey,
),

backgroundColor 是导航栏背景色。

selectedItemColor 是选中项的颜色,用主色。

unselectedItemColor 是未选中项的颜色,用灰色。


深色主题配置

dart 复制代码
static ThemeData darkTheme = ThemeData(
  useMaterial3: true,
  brightness: Brightness.dark,
  primaryColor: primaryColor,
  colorScheme: ColorScheme.dark(
    primary: primaryColor,
    secondary: secondaryColor,
    tertiary: accentColor,
    surface: darkCard,
    background: darkBg,
  ),

深色主题的结构和浅色一样,只是颜色不同。

brightness: Brightness.dark 告诉 Flutter 这是深色主题。

注意 primaryColor 保持不变,品牌色在两种主题下应该一致。


深色模式的背景色

dart 复制代码
scaffoldBackgroundColor: darkBg,

深色背景用深蓝色(#1A1A2E)而不是纯黑,更有层次感,也更护眼。

纯黑背景在 OLED 屏幕上虽然省电,但和其他元素对比太强烈。


深色模式的 AppBar

dart 复制代码
appBarTheme: const AppBarTheme(
  backgroundColor: darkBg,
  foregroundColor: Colors.white,
  elevation: 0,
  centerTitle: true,
),

AppBar 背景和页面背景一致,形成整体感。

文字用白色,在深色背景上清晰可读。


深色模式的卡片

dart 复制代码
cardTheme: CardTheme(
  color: darkCard,
  elevation: 2,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),

卡片用稍浅的深蓝色(#16213E),和背景区分开。

深色模式下卡片颜色要比背景浅一点,才能看出层次。


深色模式的底部导航栏

dart 复制代码
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
  backgroundColor: darkCard,
  selectedItemColor: primaryColor,
  unselectedItemColor: Colors.grey,
),

导航栏用卡片色,和页面背景有区分。

选中项依然用主色,保持品牌一致性。


在 App 中应用主题

dart 复制代码
MaterialApp(
  title: '微动漫',
  theme: AppTheme.lightTheme,
  darkTheme: AppTheme.darkTheme,
  themeMode: ThemeMode.system,
  home: const HomeScreen(),
)

theme 是浅色主题,darkTheme 是深色主题。

themeMode 控制使用哪个主题:

  • ThemeMode.light:强制浅色
  • ThemeMode.dark:强制深色
  • ThemeMode.system:跟随系统

更多组件主题

可以配置更多组件的默认样式:

dart 复制代码
static ThemeData lightTheme = ThemeData(
  // 基础配置
  
  // 按钮主题
  elevatedButtonTheme: ElevatedButtonThemeData(
    style: ElevatedButton.styleFrom(
      backgroundColor: primaryColor,
      foregroundColor: Colors.white,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
    ),
  ),
  
  // 输入框主题
  inputDecorationTheme: InputDecorationTheme(
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(12),
    ),
    focusedBorder: OutlineInputBorder(
      borderRadius: BorderRadius.circular(12),
      borderSide: const BorderSide(color: primaryColor, width: 2),
    ),
  ),
  
  // 文本主题
  textTheme: const TextTheme(
    headlineLarge: TextStyle(fontWeight: FontWeight.bold),
    bodyLarge: TextStyle(height: 1.6),
  ),
);

elevatedButtonTheme 配置 ElevatedButton 的默认样式。

inputDecorationTheme 配置输入框的默认样式。

textTheme 配置各种文本样式。


获取主题颜色

在组件中获取主题颜色:

dart 复制代码
// 获取主色
final primaryColor = Theme.of(context).primaryColor;

// 获取 ColorScheme
final colorScheme = Theme.of(context).colorScheme;
final secondary = colorScheme.secondary;

// 判断是否深色模式
final isDark = Theme.of(context).brightness == Brightness.dark;

// 获取文本主题
final textTheme = Theme.of(context).textTheme;
final headline = textTheme.headlineLarge;

Theme.of(context) 获取当前主题,然后访问各种属性。


动态切换主题

配合 Provider 实现动态切换:

dart 复制代码
class ThemeProvider extends ChangeNotifier {
  ThemeMode _themeMode = ThemeMode.system;

  ThemeMode get themeMode => _themeMode;

  void setTheme(ThemeMode mode) {
    _themeMode = mode;
    notifyListeners();
  }
}
dart 复制代码
Consumer<ThemeProvider>(
  builder: (context, themeProvider, child) {
    return MaterialApp(
      theme: AppTheme.lightTheme,
      darkTheme: AppTheme.darkTheme,
      themeMode: themeProvider.themeMode,
      home: const HomeScreen(),
    );
  },
)

Provider 管理主题状态,切换时通知 MaterialApp 重建。


主题扩展

可以添加自定义的主题属性:

dart 复制代码
@immutable
class CustomColors extends ThemeExtension<CustomColors> {
  final Color? success;
  final Color? warning;
  final Color? error;

  const CustomColors({
    this.success,
    this.warning,
    this.error,
  });

  @override
  CustomColors copyWith({
    Color? success,
    Color? warning,
    Color? error,
  }) {
    return CustomColors(
      success: success ?? this.success,
      warning: warning ?? this.warning,
      error: error ?? this.error,
    );
  }

  @override
  CustomColors lerp(ThemeExtension<CustomColors>? other, double t) {
    if (other is! CustomColors) return this;
    return CustomColors(
      success: Color.lerp(success, other.success, t),
      warning: Color.lerp(warning, other.warning, t),
      error: Color.lerp(error, other.error, t),
    );
  }
}
dart 复制代码
static ThemeData lightTheme = ThemeData(
  // 其他配置
  extensions: [
    const CustomColors(
      success: Colors.green,
      warning: Colors.orange,
      error: Colors.red,
    ),
  ],
);

使用时:

dart 复制代码
final customColors = Theme.of(context).extension<CustomColors>()!;
final successColor = customColors.success;

小结

主题配置涉及的技术点:ThemeDataColorSchemeMaterial 3各组件主题Theme.of(context)ThemeExtension

主题设计原则:主色代表品牌、背景色不用纯色、深色模式卡片比背景浅、品牌色两种主题一致。

好的主题配置能让 App 视觉统一、易于维护、支持深色模式,是 Flutter 开发的重要基础。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
kk”2 小时前
C++智能指针
开发语言·c++
MX_93592 小时前
以配置非自定义bean来演示bean的实例化方式
java·开发语言·后端
时光慢煮2 小时前
Flutter × OpenHarmony 跨端开发实战:动态显示菜单详解
flutter·华为·开源·openharmony
2501_944521592 小时前
Flutter for OpenHarmony 微动漫App实战:动漫卡片组件实现
android·开发语言·javascript·flutter·ecmascript
lina_mua2 小时前
Cursor模型选择完全指南:为前端开发找到最佳AI助手
java·前端·人工智能·编辑器·visual studio
董世昌412 小时前
null和undefined的区别是什么?
java·前端·javascript
superman超哥2 小时前
派生宏(Derive Macro)的工作原理:编译时元编程的艺术
开发语言·rust·开发工具·编程语言·rust派生宏·derive macro·rust元编程
easyboot2 小时前
C#使用pythonnet简单示例
开发语言·python·c#
软弹2 小时前
Vue2 的数据响应式原理&&给实例新增响应式属性
前端·javascript·vue.js