【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现

【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现

📚 目录

[【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现](#【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现)

[📝 摘 要](#📝 摘 要)

[🔍 1 概述](#🔍 1 概述)

[1.1 开发背景](#1.1 开发背景)

[1.2 开发目标](#1.2 开发目标)

[1.3 核心技术栈](#1.3 核心技术栈)

[🛠️ 2 开发环境准备](#🛠️ 2 开发环境准备)

[2.1 环境配置](#2.1 环境配置)

[2.2 本地资源配置](#2.2 本地资源配置)

[2.3 我的页面目录结构](#2.3 我的页面目录结构)

[🧩 3 我的页面功能实现](#🧩 3 我的页面功能实现)

[3.1 主页面入口实现](#3.1 主页面入口实现)

[3.2 核心组件实现](#3.2 核心组件实现)

[3.3 子页面实现](#3.3 子页面实现)

[📱 4 运行验证与效果展示](#📱 4 运行验证与效果展示)

[4.1 我的主页面](#4.1 我的主页面)

[4.2 子页面效果](#4.2 子页面效果)

[🎯 5 总结与拓展](#🎯 5 总结与拓展)

[5.1 总结](#5.1 总结)

[5.2 拓展方向](#5.2 拓展方向)

[📚 6 参考资料](#📚 6 参考资料)


📝 摘 要

本文记录开源鸿蒙跨平台开发先锋训练营 DAY8~DAY13 的实践成果,聚焦底部选项卡适配与我的页面模块化落地。开发中严格遵循项目 "页面级模块化" 规范,搭建了 pages/mine/ 专属目录,内含 components/、models/ 子目录及完整子页面文件,实现组件与业务逻辑的解耦;完成底部选项卡与多页面的联动适配,以及我的页面从用户信息展示到收藏、设置等子页面的全功能静态路由实现,代码结构清晰,符合鸿蒙跨平台开发规范。

🔍 1 概述

1.1 开发背景

在基于 Flutter 的跨端美食类应用开发中,我的页面是承载用户个人数据、系统设置的核心模块。为了保持项目的模块化与可维护性,我延续了应用中其他页面(如首页、美食、动态)的开发规范,对我的页面进行了组件化拆分与功能实现。

1.2 开发目标

📌 完成我的页面从 0 到 1 的模块化搭建,包含用户信息展示、我的收藏、浏览历史、我的发布、设置、帮助与反馈等核心功能。

📌 解决网络图片加载失败、未使用导入警告等开发问题,提升界面稳定性与代码整洁度。

📌 保持与现有项目目录结构的一致性,遵循 "页面级模块化" 设计原则。

1.3 核心技术栈

⚡ 跨平台框架:Flutter(兼容OpenHarmony)

💻 开发工具:VS Code(代码编写)、DevEco Studio 6.0.0 Release(鸿蒙设备调试)

📊 资源管理:pubspec.yaml 本地资源配置

🛠️ 2 开发环境准备

2.1 环境配置

🚀 Flutter环境:安装 Flutter 3.27.5版本,配置flutter-OHOS-1.0.1(鸿蒙适配分支)分支(兼容 OpenHarmony);

📱 鸿蒙环境:安装DevEco Studio 6.0.0 Release,配置 OpenHarmony SDK(API Version 20(6.0.0.47)),创建鸿蒙模拟器;

📂 项目初始化:基于现有flutter_harmonyos工程,调整目录结构,安装依赖。

2.2 本地资源配置

在 pubspec.yaml 中声明推荐页面图片资源路径,确保图片正常加载:

复制代码
flutter:
  uses-material-design: true
  assets:
    - assets/images/
    - assets/images/foods/               # 美食卡片图片
    - assets/images/food_show/           # 美食页相关图片
    - assets/images/food_show/dynamic/   # 清单页动态图
    - assets/images/food_show/star/      # 排行页达人头像
    - assets/images/food_show/task/      # 任务中心图标
    - assets/images/food_note/           # 动态模块根资源
    - assets/images/food_note/avatar/    # 用户头像资源
    - assets/images/food_note/dynamic/   # 动态图片资源
    - assets/images/eat_what/            # 推荐页面资源
    - assets/images/mine/                # 我的页面资源

2.3 我的页面目录结构

遵循项目现有 "页面级模块化" 规范,每个模块独立维护 components、models、子页面等文件,目录结构如下:

复制代码
lib/
└─ pages/
   └─ mine/
      ├─ components/          # 页面子组件
      │  ├─ user_info_widget.dart            # 用户信息卡片组件
      │  ├─ mine_function_item.dart          # 功能列表条目组件
      │  └─ mine_section_widget.dart         # 功能分组标题组件
      ├─ models/              # 页面专属模型
      │  ├─ user_model.dart                  # 用户信息模型
      │  └─ mine_function_model.dart         # 功能条目模型
      ├─ mine_page.dart       # 主页面入口
      ├─ my_collection_page.dart             # 我的收藏页面
      ├─ my_history_page.dart                # 我的浏览历史页面
      ├─ my_publish_page.dart                # 我的发布页面
      ├─ settings_page.dart                  # 设置页面
      └─ feedback_page.dart                  # 帮助与反馈页面

🧩 3 我的页面功能实现

3.1 主页面入口实现

mine_page.dart 作为"我的"页面的主入口,负责整合所有子组件与功能条目:

✅ 用户信息区:通过 UserInfoWidget 展示昵称、个性签名。

✅ 功能分组:通过 MineSectionWidget 划分 "我的内容" 与 "系统设置" 模块。

✅ 功能条目:通过 MineFunctionItem 统一实现可点击的功能入口。

复制代码
// mine/                # 我的页面
// lib/pages/mine/mine_page.dart(我的)
import 'package:flutter/material.dart';
import 'components/user_info_widget.dart';
import 'components/mine_section_widget.dart';
import 'components/mine_function_item.dart';
// 导入子页面
import 'my_collection_page.dart';
import 'my_history_page.dart';
import 'settings_page.dart';
import 'feedback_page.dart';
import 'my_publish_page.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          // 用户信息区
          const UserInfoWidget(
            userName: '美食爱好者',
            signature: '分享美食,记录生活',
          ),
          // 我的内容分组
          const MineSectionWidget(title: '我的内容'),
          MineFunctionItem(
            icon: Icons.bookmark_border,
            title: '我的收藏',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const MyCollectionPage()),
            ),
          ),
          MineFunctionItem(
            icon: Icons.history,
            title: '浏览历史',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const MyHistoryPage()),
            ),
          ),
          // 我的发布功能条目
          MineFunctionItem(
            icon: Icons.edit_note, // 匹配发布的图标
            title: '我的发布',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const MyPublishPage()),
            ),
          ),
          // 系统设置分组
          const MineSectionWidget(title: '系统设置'),
          MineFunctionItem(
            icon: Icons.settings,
            title: '设置',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const SettingsPage()),
            ),
          ),
          MineFunctionItem(
            icon: Icons.help_outline,
            title: '帮助与反馈',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const FeedbackPage()),
            ),
          ),
        ],
      ),
    );
  }
}

3.2 核心组件实现

user_info_widget.dart:用户信息卡片组件。

UserInfoWidget(用户信息卡片):

"我的" 页面顶部核心组件,展示用户头像(支持网络头像 / 本地默认占位图,加载失败自动兜底)、昵称、个性签名;内置头像右下角编辑入口,支持扩展积分 / 等级等额外信息,样式统一且可灵活定制。

复制代码
// user_info_widget.dart   # 用户信息卡片组件
import 'package:flutter/material.dart';
// 我的页面用户信息卡片组件
// 包含:头像、昵称、个性签名、编辑入口,支持扩展积分/等级等信息
class UserInfoWidget extends StatelessWidget {
  final String userName;  // 用户名(默认显示"美食爱好者")
  final String? signature;  // 个性签名(可选,默认显示"分享美食,记录生活")
  final String? avatarUrl;  // 用户头像URL(默认显示本地占位图)
  final VoidCallback? onEditTap;  // 编辑信息点击回调
  final String? extraInfo;  // 积分/等级提示(可选,如"积分: 128")

  const UserInfoWidget({
    super.key,
    this.userName = "美食爱好者",
    this.signature = "分享美食,记录生活",
    this.avatarUrl,
    this.onEditTap,
    this.extraInfo,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          // 1. 用户头像
          Stack(
            children: [
              ClipOval(
                child: avatarUrl != null
                    ? // 网络头像
                    Image.network(
                        avatarUrl!,
                        width: 70,
                        height: 70,
                        fit: BoxFit.cover,
                        // 加载失败时显示默认头像
                        errorBuilder: (context, error, stackTrace) => _defaultAvatar(),
                      )
                    : // 默认本地头像
                    _defaultAvatar(),
              ),
              // 头像右下角编辑小图标
              Positioned(
                bottom: 0,
                right: 0,
                child: GestureDetector(
                  onTap: onEditTap,
                  child: Container(
                    width: 24,
                    height: 24,
                    decoration: BoxDecoration(
                      color: const Color(0xFFFC6940),
                      borderRadius: BorderRadius.circular(12),
                      border: Border.all(color: Colors.white, width: 2),
                    ),
                    child: const Icon(
                      Icons.edit,
                      size: 14,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ],
          ),
          const SizedBox(width: 16),
          // 2. 用户信息(昵称、签名、额外信息)
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  userName,
                  style: const TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Color(0xFF333333),
                  ),
                ),
                if (signature != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      signature!,
                      style: TextStyle(
                        fontSize: 14,
                        color: const Color(0xFF999999),
                        // 签名过长时省略
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                  ),
                if (extraInfo != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 6),
                    child: Text(
                      extraInfo!,
                      style: const TextStyle(
                        fontSize: 12,
                        color: Color(0xFFFC6940),
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  /// 默认占位头像(本地资源,在pubspec.yaml中配置assets)
  Widget _defaultAvatar() {
    return Image.asset(
      'assets/images/mine/avatar_default.png', // 本地头像路径
      width: 70,
      height: 70,
      fit: BoxFit.cover,
    );
  }
}

mine_function_item.dart:功能列表条目组件。

MineFunctionItem(功能条目组件):

统一功能条目的样式(图标 + 标题 + 右侧默认箭头 / 自定义提示组件),内置 Material Design 点击水波纹交互;支持点击回调、自定义图标 / 标题颜色、可选底部分割线,适配"我的"页面及应用内所有功能入口场景。

复制代码
//  mine_function_item.dart # 功能列表条目组件
import 'package:flutter/material.dart';
// 我的页面统一功能条目组件
// 支持:图标、标题、右侧箭头、点击回调、自定义右侧提示
class MineFunctionItem extends StatelessWidget {
  final IconData icon;  // 左侧功能图标
  final String title;  // 功能标题文字
  final VoidCallback? onTap;  // 点击回调事件
  final Widget? rightWidget;  // 右侧自定义提示(如数字、"NEW"标签,默认显示箭头)
  final Color iconColor;  // 图标颜色(默认主题色,可自定义)
  final Color titleColor;  // 标题文字颜色(默认黑色,可自定义)
  final bool showDivider;  // 是否显示底部分割线(默认显示)

  const MineFunctionItem({
    super.key,
    required this.icon,
    required this.title,
    this.onTap,
    this.rightWidget,
    this.iconColor = const Color(0xFFFC6940), // 适配美食APP的暖色调主题
    this.titleColor = const Color(0xFF333333),
    this.showDivider = true,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      // 点击水波纹效果,符合Material Design规范
      onTap: onTap,
      borderRadius: BorderRadius.circular(0),
      child: Container(
        color: Colors.white,
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
        child: Column(
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                // 左侧图标
                Icon(
                  icon,
                  size: 22,
                  color: iconColor,
                ),
                const SizedBox(width: 12), // 图标与标题间距
                // 功能标题
                Expanded(
                  child: Text(
                    title,
                    style: TextStyle(
                      fontSize: 16,
                      color: titleColor,
                    ),
                  ),
                ),
                // 右侧组件(默认箭头,可自定义)
                rightWidget ??
                    const Icon(
                      Icons.arrow_forward_ios,
                      size: 16,
                      color: Color(0xFFCCCCCC),
                    ),
              ],
            ),
            // 底部分割线(可选)
            if (showDivider)
              const Padding(
                padding: EdgeInsets.only(left: 48, top: 14), // 对齐标题位置
                child: Divider(
                  height: 1,
                  color: Color(0xFFF5F5F5),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

mine_section_widget.dart:功能分组标题组件。

MineSectionWidget(功能分组标题):

用于"我的"页面划分功能模块(如"我的内容"、"系统设置")的分组标题;支持自定义标题文字、左侧间距(适配不同布局)、文字颜色,内置固定的上下间距(上12dp / 下8dp),统一分组标题的视觉样式。

复制代码
// mine_section_widget.dart# 功能分组标题组件
import 'package:flutter/material.dart';
// 我的页面功能分组标题组件
// 示例:"我的内容"、"系统设置" 等分组标题
class MineSectionWidget extends StatelessWidget {
  final String title;  // 分组标题文字
  final double paddingLeft;  // 标题左侧间距(默认16dp,适配不同布局)
  final Color textColor;  // 标题文字颜色(默认灰色,可自定义)

  const MineSectionWidget({
    super.key,
    required this.title,
    this.paddingLeft = 16.0,
    this.textColor = const Color(0xFF666666),
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      // 上下间距12dp,左侧自定义间距,右侧16dp
      padding: EdgeInsets.fromLTRB(paddingLeft, 12, 16, 8),
      child: Text(
        title,
        style: TextStyle(
          fontSize: 14,
          fontWeight: FontWeight.w500,
          color: textColor,
        ),
      ),
    );
  }
}

3.3 子页面实现

my_collection_page.dart(我的收藏):使用 ListView.builder 展示收藏列表。

复制代码
// my_collection_page.dart # 我的收藏页面
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('我的收藏'),
        centerTitle: true,
      ),
      body: ListView.builder(
        itemCount: 10, // 模拟数据
        itemBuilder: (context, index) {
          return ListTile(
            leading: ClipRRect(
              borderRadius: BorderRadius.circular(8),
              // 替换为本地图片加载(删除Image.network,改用Image.asset)
              child: Image.asset(
                'assets/images/mine/default-food.png', // 本地图片路径
                width: 60,
                height: 60,
                fit: BoxFit.cover,
                // 本地图加载失败的保险处理(路径正确则不会触发)
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                    width: 60,
                    height: 60,
                    color: Colors.grey[200],
                    child: const Icon(Icons.image, color: Colors.grey, size: 24),
                  );
                },
              ),
            ),
            title: Text('收藏过的美食 $index'),
            subtitle: const Text('收藏于 2026-02-01'),
            onTap: () {
              // 跳转美食详情
            },
          );
        },
      ),
    );
  }
}

my_history_page.dart(浏览历史):

复制代码
// my_history_page.dart    # 我的浏览历史页面
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('浏览历史'),
        centerTitle: true,
        actions: [
          TextButton(
            onPressed: () {
              // 清空历史逻辑
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('浏览历史已清空')),
              );
            },
            child: const Text(
              '清空',
              style: TextStyle(color: Color(0xFFFC6940)),
            ),
          ),
        ],
      ),
      body: ListView.builder(
        itemCount: 8, // 模拟数据
        itemBuilder: (context, index) {
          return ListTile(
            leading: ClipRRect(
              borderRadius: BorderRadius.circular(8),
              // 替换为本地图片加载(删除Image.network,改用Image.asset)
              child: Image.asset(
                'assets/images/mine/default-food.png', // 本地图片路径
                width: 60,
                height: 60,
                fit: BoxFit.cover,
                // 本地图加载失败的保险处理(路径正确则不会触发)
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                    width: 60,
                    height: 60,
                    color: Colors.grey[200],
                    child: const Icon(Icons.image, color: Colors.grey, size: 24),
                  );
                },
              ),
            ),
            title: Text('浏览过的美食 $index'),
            subtitle: const Text('浏览于 2026-02-01'),
            onTap: () {
              // 跳转美食详情
            },
          );
        },
      ),
    );
  }
}

my_publish_page.dart(我的发布):

复制代码
// my_publish_page.dart    # 我的发布页面
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('我的发布'),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(
              Icons.article_outlined,
              size: 80,
              color: Color(0xFFCCCCCC),
            ),
            const SizedBox(height: 16),
            const Text(
              '您还没有发布过内容',
              style: TextStyle(
                fontSize: 16,
                color: Color(0xFF999999),
              ),
            ),
            const SizedBox(height: 24),
            ElevatedButton(
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(0xFFFC6940), // 匹配APP主题色
                padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
              ),
              onPressed: () {
                // 这里可以跳转"发布美食"的页面(后续可补充路由)
              },
              child: const Text(
                '去发布',
                style: TextStyle(color: Colors.white, fontSize: 16),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

settings_page.dart(设置):

复制代码
// settings_page.dart  # 设置页面
import 'package:flutter/material.dart';

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

  @override
  State<SettingsPage> createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  // 主题颜色选择
  List<Color> themeColors = [
    const Color(0xFFFF5722),
    const Color(0xFF4CAF50),
    const Color(0xFF2196F3),
    const Color(0xFF9C27B0),
    const Color(0xFFFFC107),
    Colors.black,
  ];
  int selectedColorIndex = 4; // 默认选中橙色

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('设置'),
        centerTitle: true,
      ),
      body: ListView(
        children: [
          // 主题切换
          const ListTile(
            title: Text('主题'),
            leading: Icon(Icons.color_lens, color: Color(0xFFFC6940)),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Wrap(
              spacing: 12,
              children: List.generate(themeColors.length, (index) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                      selectedColorIndex = index;
                    });
                  },
                  child: Container(
                    width: 40,
                    height: 40,
                    decoration: BoxDecoration(
                      color: themeColors[index],
                      borderRadius: BorderRadius.circular(20),
                      border: selectedColorIndex == index
                          ? Border.all(color: Colors.white, width: 3)
                          : null,
                      boxShadow: [
                        BoxShadow(
                          color: Colors.black.withOpacity(0.1),
                          blurRadius: 4,
                        ),
                      ],
                    ),
                  ),
                );
              }),
            ),
          ),
          const Divider(height: 1),
          // 多语言
          ListTile(
            title: const Text('多语言'),
            leading: const Icon(Icons.language, color: Color(0xFFFC6940)),
            trailing: const Text('跟随系统'),
            onTap: () {
              // 多语言选择逻辑
            },
          ),
          const Divider(height: 1),
          // 清除缓存
          ListTile(
            title: const Text('清除缓存'),
            leading: const Icon(Icons.delete_sweep, color: Color(0xFFFC6940)),
            trailing: const Text('32.66M'),
            onTap: () {
              // 清除缓存逻辑
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('缓存已清除')),
              );
            },
          ),
          const Divider(height: 1),
          // 关于我们
          ListTile(
            title: const Text('关于我们'),
            leading: const Icon(Icons.info_outline, color: Color(0xFFFC6940)),
            onTap: () {
              // 跳转关于页面
            },
          ),
        ],
      ),
    );
  }
}

feedback_page.dart(帮助与反馈):

复制代码
// feedback_page.dart      # 帮助与反馈页面
import 'package:flutter/material.dart';

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

  @override
  State<FeedbackPage> createState() => _FeedbackPageState();
}

class _FeedbackPageState extends State<FeedbackPage> {
  final TextEditingController _feedbackController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('帮助与反馈'),
        centerTitle: true,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Expanded(
              child: TextField(
                controller: _feedbackController,
                maxLines: null,
                expands: true,
                textAlignVertical: TextAlignVertical.top,
                decoration: const InputDecoration(
                  hintText: '请描述您的问题或建议...',
                  border: OutlineInputBorder(),
                  contentPadding: EdgeInsets.all(12),
                ),
              ),
            ),
            const SizedBox(height: 16),
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: const Color(0xFFFC6940),
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 14),
                ),
                onPressed: () {
                  // 提交反馈逻辑
                  if (_feedbackController.text.isNotEmpty) {
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(content: Text('反馈提交成功,感谢您的建议!')),
                    );
                    Navigator.pop(context);
                  } else {
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(content: Text('请输入您的反馈内容')),
                    );
                  }
                },
                child: const Text('提交'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

📱 4 运行验证与效果展示

4.1 我的主页面

展示用户信息与所有功能入口,点击条目可直接跳转至对应子页面,界面风格统一,交互流畅。

4.2 子页面效果

我的收藏页面,静态列表展示,图片加载稳定;

浏览历史,设计支持清空功能(暂时不能使用),交互反馈及时;

我的发布,空状态引导清晰,按钮交互友好;

设置,计划设计主题切换、缓存清除功能;

帮助与反馈,文本输入与提交功能正常。

🎯 5 总结与拓展

5.1 总结

本次实现遵循了项目现有的模块化设计规范,通过组件化拆分,完成了我的页面的基础功能开发。包括:

✅ 模块化结构:每个页面独立维护组件与模型,代码职责清晰,可维护性高。

✅ 容错处理:网络图片加载失败时自动切换本地占位图,提升界面稳定性。

✅ 代码整洁:通过删除未使用导入、局部 const 优化,消除所有 IDE 警告。

5.2 拓展方向

完善已有页面布局,为开源鸿蒙跨平台应用全面集成动效能力,覆盖页面转场、组件交互、数据加载等核心场景,提升应用视觉体验与交互流畅度,并完成开源鸿蒙设备运行验证。

📚 6 参考资料

🔗 参考前文:

https://blog.csdn.net/m0_74451345/article/details/156915775?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157024056?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157032531?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157094159?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157464927?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157505773?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157542849?spm=1001.2014.3001.5502

https://blog.csdn.net/m0_74451345/article/details/157583805?spm=1001.2014.3001.5501

🔗 参考三方库:

OpenHarmony兼容的三方库:https://gitcode.com/openharmony-tpc/flutter_packages

🔗文章中AtomGit开源项目个人仓库链接:

https://atomgit.com/zhangxupeng2025/flutter_HmProject

ℹ️ 博客说明:本文为训练营实战记录,代码可在我的AtomGit个人公开仓库克隆到本地配置后直接运行(部分资源需要本地配置,比如需替换本地图片资源),后续将完善已有页面布局,为开源鸿蒙跨平台应用全面集成动效能力,覆盖页面转场、组件交互、数据加载等核心场景,提升应用视觉体验与交互流畅度,文中也有许多待优化点,欢迎大家关注交流~

最后,

欢迎加入开源鸿蒙跨平台社区:

https://openharmonycrossplatform.csdn.net

相关推荐
灰灰勇闯IT2 小时前
Flutter for OpenHarmony:悬浮按钮(FloatingActionButton)最佳实践 —— 强化核心操作,提升用户效率
flutter·华为·交互
雨季6662 小时前
Flutter 三端应用实战:OpenHarmony “心流之泉”——在碎片洪流中,为你筑一眼专注的清泉
开发语言·前端·flutter·交互
一起养小猫3 小时前
Flutter for OpenHarmony 进阶:表达式解析算法与计算器核心实现
算法·flutter·harmonyos
听麟3 小时前
HarmonyOS 6.0+ PC端系统级桌面插件开发实战:ArkUI Widget进阶与系统交互深度集成
华为·交互·harmonyos
不爱吃糖的程序媛3 小时前
Flutter 三方库鸿蒙(OHOS)适配分析流程
flutter·华为·harmonyos
2301_796512524 小时前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:Lazyload 懒加载(懒加载的图片)
前端·javascript·react native·react.js·ecmascript·harmonyos
mocoding4 小时前
我这样用鸿蒙化Flutter三方库file_selector实现单图片和多图片选择
flutter·华为·harmonyos
听麟4 小时前
HarmonyOS 6.0+ PC端视频剪辑工具开发实战:Media Kit进阶与硬件加速渲染落地
华为·harmonyos
浩宇软件开发4 小时前
基于OpenHarmony鸿蒙开发医院预约挂号系统(前端后端分离)
前端·华为·harmonyos