现在位置: 首页 > Flutter 教程 > 正文

Flutter 主题与样式

本节将介绍 Flutter 中的主题配置,包括 Material Design 主题、自定义主题和深色模式。


ThemeData - 应用主题

使用 ThemeData 可以统一配置应用的主题颜色、字体、样式等。

实例:配置应用主题

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData(
        // 主色调
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.light,
        ),
        // 使用 Material 3
        useMaterial3: true,
        // 字体
        fontFamily: 'Roboto',
        // 应用栏主题
        appBarTheme: const AppBarTheme(
          centerTitle: true,
          elevation: 0,
        ),
        // 按钮主题
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
          ),
        ),
        // 输入框主题
        inputDecorationTheme: InputDecorationTheme(
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8),
          ),
          filled: true,
        ),
      ),
      home: const MyHomePage(),
    ),
  );
}

Theme.of - 使用主题

在 Widget 中使用 Theme.of(context) 获取当前主题。

实例:使用主题颜色

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

  @override
  Widget build(BuildContext context) {
    // 获取主题
    final theme = Theme.of(context);

    return Column(
      children: [
        // 使用主题色
        Container(
          color: theme.colorScheme.primary,
          padding: const EdgeInsets.all(16),
          child: Text(
            '主要颜色',
            style: TextStyle(color: theme.colorScheme.onPrimary),
          ),
        ),
        const SizedBox(height: 16),
        // 使用次要色
        Container(
          color: theme.colorScheme.secondary,
          padding: const EdgeInsets.all(16),
          child: Text(
            '次要颜色',
            style: TextStyle(color: theme.colorScheme.onSecondary),
          ),
        ),
        const SizedBox(height: 16),
        // 使用错误色
        Container(
          color: theme.colorScheme.error,
          padding: const EdgeInsets.all(16),
          child: Text(
            '错误颜色',
            style: TextStyle(color: theme.colorScheme.onError),
          ),
        ),
      ],
    );
  }
}

深色模式

实例:深色模式支持

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData(
        // 浅色主题
        brightness: Brightness.light,
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      darkTheme: ThemeData(
        // 深色主题
        brightness: Brightness.dark,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.dark,
        ),
      ),
      // 同时启用(可选)
      themeMode: ThemeMode.system,  // 根据系统设置
      // themeMode: ThemeMode.light   // 强制浅色
      // themeMode: ThemeMode.dark    // 强制深色
      home: const ThemeTogglePage(),
    ),
  );
}

// 切换主题
class ThemeTogglePage extends StatelessWidget {
  const ThemeTogglePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('主题切换')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('当前主题'),
            const SizedBox(height: 20),
            // 切换主题按钮
            ElevatedButton(
              onPressed: () {
                final currentMode = Theme.of(context).brightness;
                if (currentMode == Brightness.light) {
                  // 切换到深色
                  Theme.of(context).setThemeMode(ThemeMode.dark);
                } else {
                  // 切换到浅色
                  Theme.of(context).setThemeMode(ThemeMode.light);
                }
              },
              child: const Text('切换主题'),
            ),
          ],
        ),
      ),
    );
  }
}

自定义样式扩展

实例:自定义 TextTheme

ThemeData(
  textTheme: const TextTheme(
    // 展示文字(大标题)
    displayLarge: TextStyle(fontSize: 57, fontWeight: FontWeight.w400),
    displayMedium: TextStyle(fontSize: 45, fontWeight: FontWeight.w400),
    displaySmall: TextStyle(fontSize: 36, fontWeight: FontWeight.w400),
    // 标题文字
    headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.w400),
    headlineMedium: TextStyle(fontSize: 28, fontWeight: FontWeight.w400),
    headlineSmall: TextStyle(fontSize: 24, fontWeight: FontWeight.w400),
    // 标题文字
    titleLarge: TextStyle(fontSize: 22, fontWeight: FontWeight.w500),
    titleMedium: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
    titleSmall: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
    // 正文文字
    bodyLarge: TextStyle(fontSize: 16, fontWeight: FontWeight.w400),
    bodyMedium: TextStyle(fontSize: 14, fontWeight: FontWeight.w400),
    bodySmall: TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
    // 标签文字
    labelLarge: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
    labelMedium: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
    labelSmall: TextStyle(fontSize: 11, fontWeight: FontWeight.w500),
  ),
)

使用 ThemeData 统一管理应用样式,可以轻松实现主题切换和样式统一,维护更方便。