【GLM-5 陪练式创意 UI 实战】第一篇:创意魔法盒 —— 用 AI 生成 “开心” 主题 Flutter UI,搞定深浅色与响应式

【GLM-5 陪练式创意 UI 实战】第一篇:创意魔法盒 ------ 用 AI 生成 "开心" 主题 Flutter UI,搞定深浅色与响应式

目录

[【GLM-5 陪练式创意 UI 实战】第一篇:创意魔法盒 ------ 用 AI 生成 "开心" 主题 Flutter UI,搞定深浅色与响应式](#【GLM-5 陪练式创意 UI 实战】第一篇:创意魔法盒 —— 用 AI 生成 “开心” 主题 Flutter UI,搞定深浅色与响应式)

[引 言](#引 言)

[1 测试背景与准备](#1 测试背景与准备)

[2 核心提示词设计](#2 核心提示词设计)

[3 情绪驱动的设计拆解(GLM-5 输出解析)](#3 情绪驱动的设计拆解(GLM-5 输出解析))

[3.1 配色方案:暖色调传递快乐感](#3.1 配色方案:暖色调传递快乐感)

[3.2 动画效果:让 UI "活" 起来](#3.2 动画效果:让 UI “活” 起来)

[4 核心代码实现与解析](#4 核心代码实现与解析)

[4.1 主题配置:深浅色模式一键切换](#4.1 主题配置:深浅色模式一键切换)

[4.2 动画管理:双控制器实现多效果联动](#4.2 动画管理:双控制器实现多效果联动)

[4.3 响应式布局:适配手机 / 桌面双端](#4.3 响应式布局:适配手机 / 桌面双端)

[4.4 核心 UI 组件:情绪与功能的融合](#4.4 核心 UI 组件:情绪与功能的融合)

[5 本地效果验证:从项目创建到运行调试](#5 本地效果验证:从项目创建到运行调试)

[5.1 项目初始化](#5.1 项目初始化)

[5.2 进入项目目录](#5.2 进入项目目录)

[5.3 替换核心代码](#5.3 替换核心代码)

[5.4 启动 Web 服务](#5.4 启动 Web 服务)

[6 实践感悟](#6 实践感悟)


✨ 主题 3:创意魔法盒 ------ 情绪驱动的动态 UI 生成器

活动仓库链接:https://atomgit.com/GitCode/0daymodel

引 言

完成【主题 1:初体验拾光 ------AI 陪练式前端新手入门】系列后,我将目光投向了主题 3:创意魔法盒 ------ 情绪驱动的动态 UI 生成器。这一主题的核心魅力在于 "让 UI 随情绪流动",而 Flutter 的跨平台特性、原生级动画支持,恰好能完美承载 "情绪驱动" 的动态设计需求。

本次我将以 "开心、明亮、活泼" 为核心情绪,借助 GLM-5 的陪练能力,从 0 到 1 生成可直接运行的 Flutter UI 组件,并学习深浅色模式切换移动端响应式适配两大核心需求,开启情绪 UI 的实战之旅。

1 测试背景与准备

1. 主题 3 核心任务

根据征文要求,情绪 UI 设计师需完成三步核心任务:

  1. 按 "开心" 情绪生成配色、动画与可运行的 Flutter 代码;
  2. 迭代生成 "科技感" 风格代码并说明差异;
  3. 整合 Demo 并部署到 AtomGit。

本篇聚焦第一步:实现 "开心" 主题的基础 UI。

2. GLM-5 参数优化

为避免代码截断,结合之前的测试经验,我对 GLM-5 做了针对性参数调整(截图如下):

  • Max Tokens:从 4096 提升至 8192,释放足够的代码输出空间;
  • Temperature:降至 0.2,保证输出代码的稳定性与聚焦性;
  • 其他参数保持默认,确保 AI 输出贴合需求、无冗余内容。

2 核心提示词设计

结合主题 3 要求与 Flutter 技术栈,我设计了相关的提示词,锁定 "情绪 UI 设计师" 角色,明确输出边界,避免 AI 发散:

复制代码
你现在是一个"情绪UI设计师",我会用文字描述我的情绪和需求,请你严格按照以下步骤执行,并且全程使用Flutter(Dart语言)实现:
1. 我当前的情绪是:我现在很开心,想要一个明亮、活泼的个人主页。
   - 生成对应的UI配色方案(明确色值)、动画效果和可直接运行的Flutter组件代码。
   - 代码必须支持深色/浅色模式切换,并且响应式适配移动端。
2. 当我后续说"现在我想换成科技感的风格"时,你需要迭代生成新的Flutter代码,并详细说明与上一版的差异。
3. 最后,生成一个完整的"情绪网页"Demo(Flutter Web),并提供部署到AtomGit的详细步骤说明。

现在,请先执行第一步:生成"开心/明亮/活泼"主题的个人主页。如果内容超过单次输出限制,请在末尾标注"[未完待续]",我会继续请求生成剩余部分。

提示词设计逻辑

  • 明确角色与技术栈:锁定 "情绪 UI 设计师",强制使用 Flutter;

  • 拆解任务步骤:先完成第一步,避免一次性需求过多导致截断;

  • 防截断约定:标注 "[未完待续]",为长内容输出兜底。

3 情绪驱动的设计拆解(GLM-5 输出解析)

基于 "开心、明亮、活泼" 的情绪,GLM-5 为我量身打造了一套贴合情绪的设计方案,完美实现了 "情绪→设计" 的转化。

复制代码
用户希望我扮演"情绪UI设计师",并使用Flutter(Dart)实现特定的UI设计。

**当前任务:**
执行第一步:生成"开心/明亮/活泼"主题的个人主页。

**需求:**
1.  **情绪:** 开心、明亮、活泼。
2.  **输出:**
    *   UI配色方案(明确色值)。
    *   动画效果。
    *   可直接运行的Flutter组件代码。
    *   支持深色/浅色模式切换。
    *   响应式适配移动端。
3.  **限制:** 如果输出太长,标注"[未完待续]"。

**第一步分析与设计:**

*   **主题(开心/明亮/活泼):**
    *   *颜色:* 高饱和度,暖色调。黄色、橙色、粉色、青色。
    *   *浅色模式:* 白色背景,明亮的强调色。
    *   *深色模式:* 深灰/黑色背景,霓虹/柔和的强调色以保持"活泼"感而不刺眼。
    *   *排版:* 圆角,俏皮的字体(Flutter中通常使用标准字体,但样式很重要)。

*   **配色方案(色值):**
    *   主色:阳光黄 (#FFD740) 或 活力橙 (#FF7043)。让我们选用一种混合了珊瑚粉 (#FF8A65) 的明亮黄色 (#FFD54F)。
    *   辅色:青色 (#4DD0E1) 或 石灰绿 (#AED581)。
    *   背景(浅色):#FAFAFA(纯白太平淡)。
    *   背景(深色):#121212 或 #1E1E1E。
    *   文本(浅色):深灰 #37474F。
    *   文本(深色):白色 #FFFFFF。

*   **动画效果:**
    *   "活泼"意味着运动。
    *   Hero头像的浮动动画。
    *   卡片的交错淡入。
    *   按钮的弹跳效果。

*   **Flutter实现细节:**
    *   `MaterialApp` 配置 `theme` 和 `darkTheme`。
    *   `ThemeData` 定义。
    *   `AnimatedBuilder` 或 `AnimationController` 用于浮动效果。
    *   `LayoutBuilder` 或 `MediaQuery` 用于响应式布局。
    *   `Switch` 或 `IconButton` 用于主题切换。

**起草代码结构:**

1.  `main.dart`:入口点。
2.  `MyApp`:主题配置。
3.  `HomePage`:主屏幕。
    *   `AppBar`:标题 + 主题切换。
    *   `Body`:`SingleChildScrollView` 或 `ListView`。
    *   `Header`:头像 + 名字 + 简介。
    *   `Stats`:关注者/帖子行。
    *   `Content`:卡片网格或列表。

**完善"活泼"方面:**
*   使用 `Container` 装饰圆角和渐变。
*   使用 `StaggeredGrid` 或简单的 `Wrap` 来营造活泼的布局感。

**分步执行计划:**

1.  **定义配色方案:** 列出十六进制代码。
2.  **描述动画:** 解释逻辑(例如,使用 `Sin` 实现浮动)。
3.  **编写代码:**
    *   导入。
    *   主函数。
    *   主题数据(浅色/深色)。
    *   主页Widget。
    *   头部Widget(动画)。
    *   卡片Widget。
    *   响应式逻辑(检查宽度)。

**起草过程中的自我修正/完善:**
*   *限制检查:* 用户要求"可直接运行"。我需要确保代码是独立的(如果可能的话,不依赖外部包,或者使用标准包如 `provider` 进行状态管理,但为了简单和单文件,`setState` 更好)。
*   *深色模式:* 需要一个变量来跟踪主题状态。
*   *响应式:* 使用 `MediaQuery.of(context).size.width`。

**起草内容:**
*   *标题:* "快乐空间"。
*   *简介:* "分享快乐与创意。"
*   *卡片:* "我的爱好"、"旅行日记"、"美食地图"。

**让我们编写实际的Flutter代码逻辑(心理草稿):**
```dart
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  late AnimationController _floatController;
  // ... 初始化动画 ...
  // ... 构建方法 ...
}
```

**配色方案定义:**
*   浅色主色:`Color(0xFFFFD54F)` (黄色)
*   浅色辅色:`Color(0xFFFF7043)` (橙色)
*   深色主色:`Color(0xFF4DD0E1)` (青色 - 在深色模式下看起来很酷)
*   深色辅色:`Color(0xFFAB47BC)` (紫色)

**响应式布局:**
*   如果宽度 < 600:列表视图(移动端)。
*   如果宽度 >= 600:网格视图(平板/桌面)。

**输出结构:**
1.  设计理念(颜色与动画)。
2.  Flutter代码块。
3.  结束语。

让我们生成回复收到!作为你的"情绪UI设计师",我非常乐意为你将这份"开心、明亮、活泼"的情绪转化为具体的Flutter代码。

以下是第一步的详细设计与实现:

### 1. 设计理念与方案

**情绪关键词:** 开心、明亮、活泼、阳光。

**UI 配色方案:**

为了传达"开心"的情绪,我们选用高饱和度、暖色调为主,搭配清新的冷色调作为点缀,营造阳光明媚的感觉。

*   **浅色模式:**
    *   主背景: `#FFF9F3` (极淡的暖白,像阳光晒过的纸张)
    *   主色调: `#FFD740` (向日葵黄,代表活力与快乐)
    *   次色调: `#FF7043` (珊瑚橙,温暖且富有亲和力)
    *   强调色: `#26A69A` (青绿色,用于按钮或链接,平衡暖色)
    *   文字色: `#37474F` (深蓝灰,比纯黑更柔和)

*   **深色模式:**
    *   主背景: `#121212` (标准Material深色背景)
    *   表面色: `#1E1E1E` (卡片背景)
    *   主色调: `#FFE57F` (亮黄色,在深色背景下更发光)
    *   次色调: `#FF8A65` (深色模式下的橙色)
    *   文字色: `#EEEEEE` (柔白)

**动画效果:**

1.  **弹性呼吸动画:** 头像和主要卡片具有轻微的缩放呼吸效果,模拟心跳或呼吸的节奏,赋予界面生命力。
2.  **交错入场:** 页面元素依次滑入,配合弹性曲线,像蹦跳着出场一样。
3.  **交互反馈:** 按钮点击时有明显的缩放与发光效果。

---

### 2. Flutter 组件代码实现

这是一个完整的 `main.dart` 文件,支持深色/浅色切换,并适配移动端。

```dart
import 'package:flutter/material.dart';
import 'dart:math' as math;

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Happy Mood UI',
      debugShowCheckedModeBanner: false,
      theme: _buildLightTheme(),
      darkTheme: _buildDarkTheme(),
      themeMode: ThemeMode.system, // 跟随系统
      home: const HappyHomePage(),
    );
  }

  // 构建明亮主题
  ThemeData _buildLightTheme() {
    final base = ThemeData.light(useMaterial3: true);
    return base.copyWith(
      scaffoldBackgroundColor: const Color(0xFFFFF9F3),
      colorScheme: base.colorScheme.copyWith(
        primary: const Color(0xFFFFD740),
        secondary: const Color(0xFFFF7043),
        tertiary: const Color(0xFF26A69A),
        surface: const Color(0xFFFFFFFF),
        onSurface: const Color(0xFF37474F),
      ),
      cardTheme: CardTheme(
        color: Colors.white,
        elevation: 4,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      ),
      textTheme: base.textTheme.apply(
        bodyColor: const Color(0xFF37474F),
        displayColor: const Color(0xFF37474F),
      ),
    );
  }

  // 构建深色主题
  ThemeData _buildDarkTheme() {
    final base = ThemeData.dark(useMaterial3: true);
    return base.copyWith(
      scaffoldBackgroundColor: const Color(0xFF121212),
      colorScheme: base.colorScheme.copyWith(
        primary: const Color(0xFFFFE57F),
        secondary: const Color(0xFFFF8A65),
        tertiary: const Color(0xFF80CBC4),
        surface: const Color(0xFF1E1E1E),
        onSurface: const Color(0xFFEEEEEE),
      ),
      cardTheme: CardTheme(
        color: const Color(0xFF1E1E1E),
        elevation: 8,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      ),
    );
  }
}

class HappyHomePage extends StatefulWidget {
  const HappyHomePage({super.key});

  @override
  State<HappyHomePage> createState() => _HappyHomePageState();
}

class _HappyHomePageState extends State<HappyHomePage>
    with TickerProviderStateMixin {
  late AnimationController _breathController;
  late AnimationController _entryController;
  
  // 模拟主题切换状态(用于演示,实际由系统控制)
  var _isDarkMode = false;

  @override
  void initState() {
    super.initState();
    
    // 1. 呼吸动画:无限循环,像心跳一样
    _breathController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1500),
    )..repeat(reverse: true);

    // 2. 入场动画:一次性
    _entryController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1200),
    )..forward();
  }

  @override
  void dispose() {
    _breathController.dispose();
    _entryController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;
    final size = MediaQuery.of(context).size;
    final isMobile = size.width < 600;

    return Scaffold(
      body: SafeArea(
        child: AnimatedBuilder(
          animation: _entryController,
          builder: (context, child) {
            return Stack(
              children: [
                // 背景装饰圆形
                Positioned(
                  top: -50,
                  right: -50,
                  child: AnimatedBuilder(
                    animation: _breathController,
                    builder: (context, _) {
                      final scale = 1.0 + _breathController.value * 0.1;
                      return Transform.scale(
                        scale: scale,
                        child: Container(
                          width: 200,
                          height: 200,
                          decoration: BoxDecoration(
                            color: colorScheme.primary.withOpacity(0.2),
                            shape: BoxShape.circle,
                          ),
                        ),
                      );
                    },
                  ),
                ),
                
                // 主要内容
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // 顶部栏:切换主题
                      _buildTopBar(colorScheme),
                      
                      // 滑动入场效果
                      SlideTransition(
                        position: Tween<Offset>(
                          begin: const Offset(0, 0.5),
                          end: Offset.zero,
                        ).animate(CurvedAnimation(
                          parent: _entryController,
                          curve: Curves.elasticOut, // 弹性曲线
                        )),
                        child: FadeTransition(
                          opacity: _entryController,
                          child: _buildContent(context, isMobile, colorScheme),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            );
          },
        ),
      ),
    );
  }

  // 顶部栏
  Widget _buildTopBar(ColorScheme colorScheme) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Text(
          "My Mood Space",
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: colorScheme.onSurface,
          ),
        ),
        IconButton(
          icon: Icon(
            _isDarkMode ? Icons.light_mode : Icons.dark_mode,
            color: colorScheme.secondary,
          ),
          onPressed: () {
            setState(() {
              _isDarkMode = !_isDarkMode;
            });
            // 实际应用中这里会调用更高层级的状态管理
            // 演示目的:仅切换本地变量,实际主题由MaterialApp控制
          },
        ),
      ],
    );
  }

  // 核心内容布局
  Widget _buildContent(BuildContext context, bool isMobile, ColorScheme colorScheme) {
    return Expanded(
      child: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(height: 20),
            _buildHeader(colorScheme),
            const SizedBox(height: 30),
            _buildStatCards(colorScheme),
            const SizedBox(height: 30),
            Text(
              "今日心情记录",
              style: Theme.of(context).textTheme.titleLarge?.copyWith(
                    fontWeight: FontWeight.bold,
                    color: colorScheme.onSurface,
                  ),
            ),
            const SizedBox(height: 15),
            _buildMoodGrid(isMobile, colorScheme),
          ],
        ),
      ),
    );
  }

  // 头像与简介
  Widget _buildHeader(ColorScheme colorScheme) {
    return Row(
      children: [
        // 头像呼吸动画
        AnimatedBuilder(
          animation: _breathController,
          builder: (context, child) {
            final value = math.sin(_breathController.value * math.pi);
            return Transform.scale(
              scale: 1.0 + (value * 0.05),
              child: Container(
                padding: const EdgeInsets.all(4),
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  border: Border.all(color: colorScheme.primary, width: 3),
                ),
                child: const CircleAvatar(
                  radius: 40,
                  backgroundImage: NetworkImage('https://picsum.photos/200'), // 随机头像
                  backgroundColor: Colors.transparent,
                ),
              ),
            );
          },
        ),
        const SizedBox(width: 20),
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                "你好,开心鬼!",
                style: TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.w800,
                  color: colorScheme.onSurface,
                ),
              ),
              const SizedBox(height: 5),
              Text(
                "今天也是元气满满的一天 ✨",
                style: TextStyle(
                  fontSize: 16,
                  color: colorScheme.onSurface.withOpacity(0.7),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  // 统计卡片
  Widget _buildStatCards(ColorScheme colorScheme) {
    return Row(
      children: [
        _buildSingleStat("128", "快乐时刻", colorScheme.primary),
        const SizedBox(width: 15),
        _buildSingleStat("56", "分享瞬间", colorScheme.secondary),
        const SizedBox(width: 15),
        _buildSingleStat("99%", "心情指数", colorScheme.tertiary),
      ],
    );
  }

  Widget _buildSingleStat(String num, String label, Color color) {
    return Expanded(
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 15),
        decoration: BoxDecoration(
          color: color.withOpacity(0.15),
          borderRadius: BorderRadius.circular(15),
        ),
        child: Column(
          children: [
            Text(num, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: color)),
            Text(label, style: TextStyle(fontSize: 12, color: color.withOpacity(0.8))),
          ],
        ),
      ),
    );
  }

  // 心情网格
  Widget _buildMoodGrid(bool isMobile, ColorScheme colorScheme) {
    final items = [
      _MoodItem("🌞", "阳光早晨", "开启美好一天"),
      _MoodItem("🍦", "甜蜜下午茶", "草莓冰淇淋"),
      _MoodItem("🎨", "创意涂鸦", "画出彩虹"),
      _MoodItem("🎵", "快乐旋律", "哼着小曲"),
    ];

    return GridView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: isMobile ? 2 : 4,
        crossAxisSpacing: 15,
        mainAxisSpacing: 15,
        childAspectRatio: 1.2,
      ),
      itemCount: items.length,
      itemBuilder: (context, index) {
        // 交错动画延迟
        return AnimatedBuilder(
          animation: _entryController,
          builder: (context, child) {
            final delay = index * 0.1;
            final animVal = Curves.easeOut.transform(
              math.max(0.0, _entryController.value - delay) / (1.0 - delay),
            );
            return Transform.scale(
              scale: animVal,
              child: Opacity(
                opacity: animVal,
                child: _buildMoodCard(items[index], colorScheme),
              ),
            );
          },
        );
      },
    );
  }

  Widget _buildMoodCard(_MoodItem item, ColorScheme colorScheme) {
    return Card(
      child: InkWell(
        onTap: () {}, // 点击交互
        borderRadius: BorderRadius.circular(20),
        child: Padding(
          padding: const EdgeInsets.all(12.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(item.emoji, style: const TextStyle(fontSize: 28)),
              const SizedBox(height: 8),
              Text(
                item.title,
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: colorScheme.onSurface,
                ),
              ),
              Text(
                item.desc,
                style: TextStyle(
                  fontSize: 12,
                  color: colorScheme.onSurface.withOpacity(0.6),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _MoodItem {
  final String emoji;
  final String title;
  final String desc;
  _MoodItem(this.emoji, this.title, this.desc);
}
```

### 3. 代码说明

1.  **响应式适配**:通过 `MediaQuery.of(context).size.width` 判断屏幕宽度,动态调整网格列数(`crossAxisCount`),在手机上显示2列,宽屏显示4列。
2.  **主题切换**:定义了 `_buildLightTheme` 和 `_buildDarkTheme`。代码中包含了一个切换按钮(演示用),实际运行时会自动跟随系统设置。
3.  **动画细节**:
    *   使用 `Curves.elasticOut` 实现"活泼"的弹性入场效果。
    *   背景的圆形装饰和头像使用了 `AnimatedBuilder` 配合 `sin` 函数实现无限循环的呼吸效果,让界面感觉是"活"的。

第一步已完成。请确认这个"开心/明亮/活泼"的风格是否符合你的预期。如果满意,请发出下一步指令:"现在我想换成科技感的风格"。

3.1 配色方案:暖色调传递快乐感

配色是情绪表达的核心,GLM-5 选用高饱和度暖色调,搭配柔和辅助色,既贴合 "开心" 情绪,又保证了视觉舒适度。

模式 主背景 主色调 次色调 强调色 文字色
浅色模式 #FFF9F3(暖白) #FFD740(向日葵黄) #FF7043(珊瑚橙) #26A69A(青绿色) #37474F(深蓝灰)
深色模式 #121212(深黑) #FFE57F(亮黄) #FF8A65(浅橙) #80CBC4(浅青绿) #EEEEEE(柔白)

设计巧思:浅色模式用暖白打底,黄色 / 橙色凸显活力;深色模式保留明亮主色,在深色背景下形成 "霓虹感",既延续活泼情绪,又符合夜间视觉习惯。

3.2 动画效果:让 UI "活" 起来

为强化 "活泼" 感,GLM-5 设计了三套核心动画,精准匹配 "开心" 的灵动氛围:

  1. 呼吸动画:头像与背景圆形装饰的无限循环缩放,模拟心跳节奏,赋予界面生命力;
  2. 弹性入场动画 :页面核心元素通过Curves.elasticOut曲线滑入,像 "蹦跳着出场";
  3. 交错入场动画:心情卡片按索引延迟显示,营造层次感与节奏感。

4 核心代码实现与解析

GLM-5 生成的main.dart是完整的可运行代码,核心分为主题配置动画管理响应式布局核心 UI 组件四大模块,以下是关键部分的解析与优化说明。

4.1 主题配置:深浅色模式一键切换

通过_buildLightTheme_buildDarkTheme封装ThemeData,结合MaterialApptheme/darkTheme参数,实现系统主题跟随,同时预留手动切换入口。

复制代码
// 明亮主题构建
ThemeData _buildLightTheme() {
  final base = ThemeData.light(useMaterial3: true);
  return base.copyWith(
    scaffoldBackgroundColor: const Color(0xFFFFF9F3),
    colorScheme: base.colorScheme.copyWith(
      primary: const Color(0xFFFFD740),
      secondary: const Color(0xFFFF7043),
      tertiary: const Color(0xFF26A69A),
    ),
    cardTheme: CardTheme(
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), // 圆角强化活泼感
    ),
  );
}

// 深色主题构建(核心差异:调整主色亮度与背景色)
ThemeData _buildDarkTheme() {
  final base = ThemeData.dark(useMaterial3: true);
  return base.copyWith(
    scaffoldBackgroundColor: const Color(0xFF121212),
    colorScheme: base.colorScheme.copyWith(
      primary: const Color(0xFFFFE57F), // 提亮黄色,适配深色背景
      secondary: const Color(0xFFFF8A65),
    ),
  );
}

4.2 动画管理:双控制器实现多效果联动

借助TickerProviderStateMixin,创建两个动画控制器,分别管理呼吸动画 (无限循环)和入场动画(一次性执行)。

复制代码
late AnimationController _breathController; // 呼吸动画控制器
late AnimationController _entryController; // 入场动画控制器

@override
void initState() {
  super.initState();
  // 呼吸动画:1500ms循环,反向重复
  _breathController = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 1500),
  )..repeat(reverse: true);

  // 入场动画:1200ms执行一次
  _entryController = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 1200),
  )..forward();
}

4.3 响应式布局:适配手机 / 桌面双端

通过MediaQuery获取屏幕宽度,动态调整网格列数,实现 "移动端 2 列、桌面端 4 列" 的自适应布局。

复制代码
final size = MediaQuery.of(context).size;
final isMobile = size.width < 600;

// 网格布局配置
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  crossAxisCount: isMobile ? 2 : 4, // 动态列数
  crossAxisSpacing: 15,
  mainAxisSpacing: 15,
  childAspectRatio: 1.2,
),

4.4 核心 UI 组件:情绪与功能的融合

  • 头部区域:带呼吸动画的头像 + 活力文案,直接传递 "开心" 情绪;
  • 统计卡片:用淡色渐变 + 圆角设计,强化活泼感,展示情绪相关数据;
  • 心情卡片:交错入场的卡片网格,搭配 emoji 图标,直观呈现情绪记录。

5 本地效果验证:从项目创建到运行调试

5.1 项目初始化

在终端执行以下命令,创建一个全新的 Flutter 项目:

复制代码
flutter create happy_mood_ui

执行后,终端会输出项目创建进度,并提示:

  • 项目代码位于 happy_mood_ui/lib/main.dart
  • 若出现 Java 与 Gradle 版本兼容提示,可按指引配置 JDK 路径或更新 Gradle 版本(本次测试优先聚焦 Web 端,可暂时忽略 Android 相关兼容提示)。

5.2 进入项目目录

执行命令进入项目根目录:

复制代码
cd happy_mood_ui

5.3 替换核心代码

将 GLM-5 生成的完整代码复制到 Flutter 项目的 lib/main.dart,覆盖原有内容,确保代码可直接运行。

5.4 启动 Web 服务

在终端执行以下命令,启动 Chrome 浏览器预览:

复制代码
flutter run -d chrome

本地运行效果如下(截图如下):

效果验证要点:

  1. 响应式适配:缩小浏览器窗口至手机尺寸,卡片自动从 4 列切换为 2 列,布局无错乱;
  2. 动画效果:头像呼吸动画流畅,页面入场有弹性,卡片交错显示有层次感;
  3. 主题切换:点击顶部明暗模式按钮,配色随模式同步切换,视觉效果统一。

6 实践感悟

  1. AI 的效率优势:传统开发中,从 "情绪分析→设计→代码实现" 需数小时,而 GLM-5 在优化参数后,10 分钟内就输出了完整的可运行代码,大幅降低了情绪 UI 的开发门槛;
  2. 参数调整的关键 :初始测试中代码截断,提升Max Tokens+ 降低Temperature后,AI 能完整输出包含动画、响应式的复杂代码,证明参数适配是 AI 辅助开发的核心前提;
  3. 情绪与技术的融合:GLM-5 能精准捕捉 "开心" 情绪的视觉特征,将暖色调、弹性动画与 Flutter 技术结合,真正实现了 "情绪驱动 UI" 的设计理念。

参与链接

GLM-5 在线体验:https://ai.atomgit.com/zai-org/GLM-5/model-inference

GLM-5 活动贴:https://ai.atomgit.com/zai-org/GLM-5/discussions

相关推荐
pcplayer1 小时前
Delphi程序和AI大模型交互
人工智能·交互
Esaka_Forever1 小时前
「为什么不用 Flutter 做游戏」「为什么不用 Cocos 做 App 界面」
flutter·游戏
RichardLau_Cx1 小时前
零依赖!纯前端 AI 辅助病例管理系统 aiCaseManage:无后端也能实现诊疗行为核验
前端·人工智能·前端开发·localstorage·医疗科技·ai辅助开发·零依赖项目
qq_24218863322 小时前
AI内容审核系统(简化版实现)
人工智能·深度学习·目标检测
啊阿狸不会拉杆2 小时前
《计算机视觉:模型、学习和推理》第 9 章-分类模型
人工智能·python·学习·算法·机器学习·计算机视觉·分类
feasibility.2 小时前
用OpenClaw做qq ai办公机器人(支持群聊关键词触发+自定义域名发送任意邮件)
人工智能·科技·阿里云·机器人·agi·qq·openclaw
多恩Stone2 小时前
【3D-AICG 系列-13】Trellis 2 的 SC-VAE 的 Training Loss 细节
人工智能·算法·3d·aigc
njsgcs2 小时前
专业名词写在rag里而不是skill里
人工智能
程序员老刘·2 小时前
Flutter 3.41 更新要点速评:主打优化,避坑AGP 9
flutter·跨平台开发·客户端开发