Flutter For OpenHarmony——开源鸿蒙跨平台TAB页面模块化开发实战

一、前言

作为开源鸿蒙跨平台训练营的一员,我选择Flutter作为技术栈完成DAY4学习。本次实战核心仅完成两项内容:将应用拆分为「首页、分类、购物车、我的」四个TAB页面模块化组件、实现底部TAB栏切换与页面状态保持。本文完全基于真实操作流程编写,记录实战踩坑与对应解决方案,贴合训练营发文要求,无任何未实操的额外内容。

二、核心实战内容(仅TAB页面+TAB底栏实现)

1. TAB页面模块化拆分

DAY4之前,我的Flutter代码全部集中在main.dart主文件中,冗余且难以维护。本次按训练营要求,对四个核心TAB页面进行模块化拆分,实现独立管理。

具体实操步骤
  1. lib根目录下新建pages文件夹,用于统一存放所有TAB页面模块;
  2. pages文件夹内依次创建HomeCategoryCartMine四个子文件夹,分别对应四个TAB页面;
  3. 每个子文件夹下新建index.dart文件,作为该TAB页面的入口组件文件,保证页面独立性。
页面标准代码(可直接复制运行)

Cart/index.dart(购物车页面)为例,其余三个页面仅修改类名和文本内容即可:

import 'package:flutter/cupertino.dart';

// 购物车TAB页面组件,类名与页面对应,遵循命名规范
class CartView extends StatefulWidget {
  const CartView({super.key});

  
  State<CartView> createState() => _CartViewState();
}

// 状态类,与Widget类一一对应,格式:_+Widget类名+State
class _CartViewState extends State<CartView> {
  
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        "购物车",
        style: TextStyle(fontSize: 18),
      ),
    );
  }
}

其余页面修改说明:
• 首页:类名HomeView、_HomeViewState,文本"首页";
• 分类:类名CategoryView、_CategoryViewState,文本"分类";
• 我的:类名MineView、_MineViewState,文本"我的"。

2. 实战踩坑与解决方案(真实遇到的 4 个问题) 这是我在实操过程中遇到的高频问题,也是新手容易踩的坑,分享具体解决方法:

1.终端无法输入命令,无法创建文件夹
◦ 问题原因:Android Studio 终端被之前运行的flutter run进程占用,输入无响应;
◦ 解决方案:按下快捷键Ctrl + C终止进程,终端弹出「终止批处理操作吗 (Y/N)?」,输入Y确认,终端恢复正常后即可执行创建命令(或直接右键可视化创建文件夹,效果一致)。
2. Widget 类与 State 类名不匹配,编译报错
◦ 问题原因:复制代码后遗漏修改状态类名,导致泛型不匹配;
◦ 解决方案:严格遵循 Flutter 命名规范,Widget类名对应_Widget类名State,例如HomeView必须对应_HomeViewState,修改后重新运行即可消除报错。
3. 新建index.dart文件后,弹出 Git 版本管理提示
◦ 问题描述:Android Studio 弹出「Add File to Git」,担心误操作影响项目运行;
◦ 解决方案:直接点击「Add」即可,该操作仅将新文件加入 Git 版本管理,方便后续代码提交、回滚,完全不影响应用正常运行;若暂时不需要版本管理,点击「Cancel」也可,后续可手动添加。
4. TAB 底栏图标加载失败,控制台提示「asset not found」
◦ 问题原因:① assets资源文件夹放错位置(误放入lib目录);② 未在pubspec.yaml中声明图标资源路径
◦ 解决方案:① 将assets文件夹移至项目根目录(与lib同级);② 在pubspec.yaml中添加如下配置,声明所有图标资源:

assets:
  - assets/ic_public_home_normal.png
  - assets/ic_public_home_active.png
  - assets/ic_public_category_normal.png
  - assets/ic_public_category_active.png
  - assets/ic_public_cart_normal.png
  - assets/ic_public_cart_active.png
  - assets/ic_public_mine_normal.png
  - assets/ic_public_mine_active.png

补充操作:配置完成后,执行flutter pub get命令,刷新资源依赖,图标即可正常加载

3. IndexedStack 实现 TAB 页面状态保持(关键优化)
问题背景
未优化前,切换 TAB 底栏页面时,之前页面的状态会完全丢失(例如分类页面滚动后,切换首页再切回分类,滚动位置会重置),影响使用体验。
实现方案
使用IndexedStack组件缓存所有 TAB 页面组件,仅显示当前索引对应的页面,其他页面不销毁,从而保持原有状态,该方案轻量高效,无需引入复杂状态管理库。
主页面main.dart完整代码(可直接复制)

import 'package:flutter/material.dart';
import 'pages/Home/index.dart';
import 'pages/Category/index.dart';
import 'pages/Cart/index.dart';
import 'pages/Mine/index.dart';

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter For OpenHarmony',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MainPage(),
    );
  }
}

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

  
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  // 存储四个TAB页面组件,与TAB底栏索引一一对应
  final List<Widget> _pages = const [
    HomeView(),
    CategoryView(),
    CartView(),
    MineView(),
  ];

  // 当前选中的TAB底栏索引,默认选中首页(索引0)
  int _currentIndex = 0;

  // 构建TAB底栏图标与文字配置
  List<BottomNavigationBarItem> _getTabBarWidget() {
    return [
      BottomNavigationBarItem(
        icon: Image.asset("assets/ic_public_home_normal.png", width: 24, height: 24),
        activeIcon: Image.asset("assets/ic_public_home_active.png", width: 24, height: 24),
        label: "首页",
      ),
      BottomNavigationBarItem(
        icon: Image.asset("assets/ic_public_category_normal.png", width: 24, height: 24),
        activeIcon: Image.asset("assets/ic_public_category_active.png", width: 24, height: 24),
        label: "分类",
      ),
      BottomNavigationBarItem(
        icon: Image.asset("assets/ic_public_cart_normal.png", width: 24, height: 24),
        activeIcon: Image.asset("assets/ic_public_cart_active.png", width: 24, height: 24),
        label: "购物车",
      ),
      BottomNavigationBarItem(
        icon: Image.asset("assets/ic_public_mine_normal.png", width: 24, height: 24),
        activeIcon: Image.asset("assets/ic_public_mine_active.png", width: 24, height: 24),
        label: "我的",
      ),
    ];
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      // 用IndexedStack包裹TAB页面,实现状态缓存与保持
      body: IndexedStack(
        index: _currentIndex,
        children: _pages,
      ),
      // 底部TAB栏实现
      bottomNavigationBar: BottomNavigationBar(
        items: _getTabBarWidget(),
        currentIndex: _currentIndex,
        // 配置选中/未选中颜色,提升视觉辨识度
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        // 点击TAB栏切换页面,更新索引
        onTap: (index) {
          setState(() {
            _currentIndex = index;
          });
        },
        // 固定TAB栏样式,避免尺寸变形
        type: BottomNavigationBarType.fixed,
      ),
    );
  }
}

4. TAB 页面基础展示与底栏优化

TAB 页面基础展示
本次实战仅实现 TAB 页面居中文字展示,在开源鸿蒙模拟器中显示清晰,无明显遮挡,满足核心功能需求,基础代码如下(以首页为例):


Widget build(BuildContext context) {
  return const Center(
    child: Text(
      "首页", 
      style: TextStyle(
        fontSize: 18, 
        fontWeight: FontWeight.bold
      )
    ),
  );
}

TAB 底栏样式优化
为提升视觉体验,对 TAB 底栏进行 3 处基础优化,均已在上述main.dart代码中实现:
1.统一图标尺寸为 24×24,避免图标拉伸、模糊;
2.区分选中 / 未选中状态(不同图标 + 蓝 / 灰颜色区分);
3.设置BottomNavigationBarType.fixed,固定底栏样式,防止窗口尺寸调整导致变形。
三、运行效果展示(附实战截图)
1. 项目目录结构截图
lib/pages目录下的四个 TAB 页面模块,每个模块均包含index.dart文件,模块化拆分完成。
lib/pages目录下的四个 TAB 页面模块,每个模块均包含index.dart文件,模块化拆分完成。
2. 首页 TAB 运行效果截图
首页文字居中显示,TAB 底栏首页图标处于选中状态
在这里插入图片描述
3. TAB 页面切换效果截图
点击 TAB 底栏「购物车」,页面流畅切换,购物车图标变为选中状态
在这里插入图片描述
4.所有 TAB 页面完整展示截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
四、实战技术思考与总结
1 . 模块化拆分是 TAB 页面开发的基础:将四个 TAB 页面独立拆分后,代码更易维护,后续扩展功能仅需修改对应模块,不会影响其他页面,符合「高内聚、低耦合」的开发思想。
2 . 轻量方案优先解决基础问题:使用IndexedStack实现状态保持,无需引入复杂状态管理库,适合基础 TAB 页面切换场景,高效且易上手。
3 . 新手踩坑是核心学习过程:终端占用、类名不匹配、资源配置错误等问题,都是新手必经之路,解决这些问题的过程,不仅掌握了技术知识点,更提升了问题排查与独立解决问题的能力。
4 .循序渐进推进开发:本次仅完成核心功能实现,未进行复杂设备适配,后续可根据学习进度,逐步完善页面内容、优化视觉样式,提升应用的兼容性与用户体验。

五、相关社区与资源
• 开源鸿蒙跨平台社区
:https://openharmonycrossplatform.csdn.net
• Flutter 官方基础文档:https://flutter.dev/docs
• 开源鸿蒙跨平台开发技术选型指导手册:https://blog.csdn.net/zl392321162/article/details/156651043
• 个人 AtomGit 仓库地址:https://gitcode.com/tjb197816/my_flutter_harmony.git
• 参考学习笔记:https://blog.csdn.net/qq_74796274/article/details/156651043

六、后续学习计划
1.完善四个 TAB 页面的详细功能,如首页添加列表展示、购物车添加商品管理功能;
2.学习 Flutter 三方库的鸿蒙化适配,解决三方库与开源鸿蒙 SDK 的兼容性问题;
3.上传完整代码至 AtomGit 仓库,持续更新实战笔记,为开源鸿蒙跨平台生态贡献力量;
4.深入学习页面适配技巧,解决多设备、刘海屏的内容遮挡问题,提升应用的跨设备兼容性。

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐