Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换

Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换
在这里插入图片描述

Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换

摘要:一个复杂的 App 通常包含多个功能模块。本文将深入讲解 Flutter 中最核心的两种多页切换模式:底部导航 (BottomNavigationBar) 和顶部选项卡 (TabBar)。我们将探讨 Material 3 风格的新组件 NavigationBar,解决页面切换时的状态丢失问题,并适配鸿蒙系统的底部手势条。

前言

打开你手机里的微信、淘宝或抖音,你会发现它们都有一个共同的架构:底部有 4-5 个图标,点击切换不同的主页面;顶部可能还有“关注/推荐/热榜”这样的分类切换。

这就是移动端最经典的 “底 Tab + 顶 Tab” 双导航架构。

本文你将学到

  • BottomNavigationBar (经典) 与 NavigationBar (Material 3) 的区别
  • TabBar + TabBarView 实现滑动切换
  • 核心难点:如何让页面在切换后不重置?(AutomaticKeepAliveClientMixin)
  • 鸿蒙适配:底部导航栏如何避开系统手势条 (Home Indicator)

一、底部导航:App 的根基

Flutter 提供了两种主流的底部导航组件。

在这里插入图片描述

1.1 经典款:BottomNavigationBar

这是最传统、兼容性最好的组件。

classMainPageextendsStatefulWidget{constMainPage({super.key});@overrideState<MainPage>createState()=>_MainPageState();}class _MainPageState extendsState<MainPage>{ int _currentIndex =0;// 页面列表finalList<Widget> _pages =[constHomePage(),constCategoryPage(),constProfilePage(),];@overrideWidgetbuild(BuildContext context){returnScaffold( body: _pages[_currentIndex],// 根据下标显示对应页面 bottomNavigationBar:BottomNavigationBar( currentIndex: _currentIndex, onTap:(index)=>setState(()=> _currentIndex = index), type:BottomNavigationBarType.fixed,// 超过3个item必须设置fixed selectedItemColor:Colors.blue, unselectedItemColor:Colors.grey, items:const[BottomNavigationBarItem(icon:Icon(Icons.home), label:'首页'),BottomNavigationBarItem(icon:Icon(Icons.category), label:'发现'),BottomNavigationBarItem(icon:Icon(Icons.person), label:'我的'),],),);}}

1.2 新潮款:NavigationBar (M3)

Material 3 引入了更高、更圆润的 NavigationBar。它自带点击涟漪和胶囊状的指示器,视觉效果更好。

NavigationBar( selectedIndex: _currentIndex, onDestinationSelected:(index)=>setState(()=> _currentIndex = index), destinations:const[NavigationDestination( icon:Icon(Icons.home_outlined), selectedIcon:Icon(Icons.home), label:'首页',),NavigationDestination( icon:Icon(Icons.explore_outlined), selectedIcon:Icon(Icons.explore), label:'发现',),// ...],)

二、顶部选项卡:TabBar

TabBar 通常用于在同一个主栏目下,切换不同的子分类(如新闻 App 的频道)。它必须配合 TabController 使用。

在这里插入图片描述

2.1 DefaultTabController (推荐)

最简单的方法是在父级包裹一个 DefaultTabController,这样我们就不用手动管理 Controller 了。

classNewsPageextendsStatelessWidget{constNewsPage({super.key});@overrideWidgetbuild(BuildContext context){returnDefaultTabController( length:3,// Tab 数量 child:Scaffold( appBar:AppBar( title:constText('资讯'), bottom:constTabBar( tabs:[Tab(text:'推荐'),Tab(text:'科技'),Tab(text:'体育'),],),), body:constTabBarView( children:[Center(child:Text('推荐内容列表')),Center(child:Text('科技内容列表')),Center(child:Text('体育内容列表')),],),),);}}

三、核心难点:页面状态保持

在这里插入图片描述

默认情况下,当你从“首页”切换到“我的”,再切回“首页”时,首页会被重建(列表滚动位置丢失,输入框清空)。这是因为 Scaffold.body 直接替换了 Widget。

3.1 解决方案:IndexedStack

如果你希望所有页面在初始化后一直存在,可以使用 IndexedStack。它会一次性加载所有页面(注意内存消耗)。

// 修改 Scaffold body body:IndexedStack( index: _currentIndex, children: _pages,// 所有页面都会被保留在 Widget 树中,只是不可见),

3.2 解决方案:AutomaticKeepAliveClientMixin

如果你使用的是 PageViewTabBarView,更推荐让子页面自己决定是否保持状态。

classHomePageextendsStatefulWidget{constHomePage({super.key});@overrideState<HomePage>createState()=>_HomePageState();}// 1. 混入 AutomaticKeepAliveClientMixinclass _HomePageState extendsState<HomePage>withAutomaticKeepAliveClientMixin{// 2. 重写 wantKeepAlive 返回 true@override bool get wantKeepAlive =>true;@overrideWidgetbuild(BuildContext context){super.build(context);// 3. 必须调用 super.buildreturnListView.builder( itemCount:100, itemBuilder:(c, i)=>ListTile(title:Text('Item $i')),);}}

四、OpenHarmony 鸿蒙适配专题

在这里插入图片描述

4.1 底部导航栏与手势条

现在的鸿蒙手机(如 Mate 60)默认开启全面屏手势,底部有一条“黑条”或“白条” (Home Indicator)。

如果你的 BottomNavigationBar 高度写死,或者没有适配 SafeArea,底部的图标可能会被这个手势条遮挡。

Flutter 的 Scaffold + BottomNavigationBar 默认已经处理了 SafeArea。但如果你使用了自定义的底部栏(比如 Stack 里的 Positioned),务必包裹 SafeArea 并设置 bottom: true

Align( alignment:Alignment.bottomCenter, child:SafeArea( child:Container( height:60, color:Colors.white, child:Row(...),),),)

五、总结

搭建一个 App 的骨架,核心就是“一底一顶”。

核心要点

  1. 底部导航:推荐使用 M3 风格的 NavigationBar,视觉更现代。
  2. 顶部 Tab:使用 DefaultTabController 配合 TabBarView 最省事。
  3. 状态保持:不想每次切换都重加载?请记住 IndexedStack (简单粗暴) 或 AutomaticKeepAliveClientMixin (精细控制)。
  4. 鸿蒙适配:时刻留意底部的安全区域,不要让按钮贴底太近。

下一篇预告

基本的页面结构都有了,但是我们现在的布局还是太“循规蹈矩”了(一行一列)。如果我要做一个 Pinterest 那样的瀑布流,或者像相册一样的网格呢?
《Flutter for OpenHarmony 实战之基础组件:第十二篇 GridView 网格布局详解》
我们将突破线性布局的限制,探索二维空间的布局艺术。


🌐 欢迎加入开源鸿蒙跨平台社区开源鸿蒙跨平台开发者社区

Read more

机器人 - 关于MIT电机模式控制

目录 一、MIT电机模式简单介绍 1.1 简单介绍 1.2 MIT模式的控制参数 1.3 使用场景 二、调试时建议 2.1 调试 2.2 问题定位 一、MIT电机模式简单介绍 1.1 简单介绍 Mixed Integrated Torque为一种混合控制模式,在同一帧CAN数据里包含 位置、速度、扭矩三类的闭环指令。驱动器里面把位置环、速度环、前馈扭矩相加,得到一个参考电流,然后再交给电流环完成精准扭矩输出。 1.2 MIT模式的控制参数 参数含义取值范围(常见)说明kp位置比例系数(刚度)0 ~ 500 (单位视驱动器而定)kp = 0 时位置环失效,

空天地联动 | 一网统飞 | 无人机巡检系统落地方案

空天地联动 | 一网统飞 | 无人机巡检系统落地方案

一、政策需求 国家将低空经济列为战略性新兴产业,“十五五” 规划明确推进一网统飞、低空智治全国覆盖,要求 2026 年前实现地市一级飞行数据全接入、空域审批一体化、低空监管数字化。多部委联合发文,推动低空通信、导航、感知基础设施建设,规范无人机飞行与空域管理,鼓励以统一平台、统一调度、统一数据模式支撑政务巡检、应急救援、生态环保、城市治理等场景规模化落地,加速低空经济从试点走向全域普及。 二、市场需求与行业痛点 1. 空域管理分散,审批效率低:多部门分头审批、流程繁琐,跨区域飞行难,“黑飞”、乱飞风险突出,安全监管压力大。 2. 部门各自为战,资源浪费严重:各单位自建系统、自购设备,重复飞行、重复投入,财政成本高、资源利用率低。 3. 数据孤岛普遍,价值难释放:巡检数据格式不统一、无法共享,难以支撑决策与协同处置。 4.

全面的System Verilog教程:从基础到高级验证

本文还有配套的精品资源,点击获取 简介:System Verilog是用于系统级验证、芯片设计与验证以及FPGA实现的强大硬件描述语言。它扩展了Verilog的基础特性,支持高级语言结构,如类、接口、任务和函数,优化了验证流程。教程内容涵盖System Verilog的基础概念、结构化编程元素、并发与同步机制、现代验证方法学、UVM验证方法论以及标准库的应用。旨在教授学生掌握System Verilog语法和高级特性,实现高效、可维护的验证代码。 1. System Verilog概述及应用领域 1.1 System Verilog的起源与发展 System Verilog是作为硬件设计和验证领域的重要语言,由Verilog发展而来,随后被进一步扩展以满足现代电子设计自动化的需要。其发展始于20世纪90年代,目的是在原有Verilog HDL的基础上,提供更为强大的设计验证功能。 1.1.1 Verilog与VHDL的区别 虽然Verilog和VHDL都是硬件描述语言(HDL),但它们在语法和使用方法上存在差异。Verilog更接近于C语言,而VHDL的语法结构则更接近