Flutter for OpenHarmony 开发指南(五):实现tabbar主菜单功能

Flutter for OpenHarmony 开发指南(五):实现tabbar主菜单功能

前言

无论是在 Android、iOS 还是新兴的 HarmonyOS 平台上,底部标签栏都是用户与应用核心功能进行交互的主要入口。它提供了一种清晰、直观的导航方式,让用户可以轻松地在不同功能模块之间切换。

在本文中,将从一个只有独立页面的初始项目开始,一步步地重构代码,最终实现一个包含“首页”和“我的”两个核心模块的 TabBar 导航结构。

目标

我的目标是将一个通过路由进行离散页面跳转的应用,改造成一个拥有固定底部导航栏的现代化应用。

改造前:

  • 应用有一个初始页面。
  • 所有页面(如登录、个人中心)通过 Navigator.pushNamed 等方法进行跳转,彼此独立。
  • 没有一个统一的主导航结构。

改造后(我的目标):

  • 应用底部有一个常驻的 TabBar,包含“首页”和“我的”两个标签。
  • 点击不同的标签,可以切换中间的主体内容区域,而 TabBar 本身保持不变。
  • 页面切换流畅,且状态能够被妥善管理。

第一步:分析初始代码

main.dart (初始状态)

import 'package:flutter/material.dart'; import 'pages/home.dart'; import 'pages/login.dart'; import 'pages/profile.dart'; import 'pages/couplet.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( /* ... Theme data ... */ ), initialRoute: '/', routes: { '/': (context) => const HomePage(), '/login': (context) => const LoginPage(), '/profile': (context) => const ProfilePage(), '/couplet': (context) => const CoupletPage(), }, ); } } 

分析:
这段代码使用 MaterialApp 的 routes 属性定义了一组命名路由。应用的根路由 '/' 直接指向 HomePage。这种方式非常适合那些需要从一个页面跳转到另一个全屏页面的场景(例如,从首页跳转到登录页)。

第二步:核心概念 - Scaffold 和 StatefulWidget

要实现 TabBar,需要引入两个 Flutter 的核心概念:

  1. Scaffold Widget: 可以把它想象成一个“脚手架”,它为构建符合 Material Design 规范的页面提供了一整套标准结构。它包含了 appBar(顶部应用栏)、body(主内容区)、floatingActionButton(浮动操作按钮)以及这次的主角——bottomNavigationBar(底部导航栏)等预设插槽。
  2. StatefulWidget(有状态组件): 我的 TabBar 需要“记住”当前哪个标签页被选中。当用户点击一个新标签时,界面需要更新以显示对应的内容。这种需要根据用户交互或内部数据变化而改变自身外观的 Widget,就是有状态组件。将使用它来保存和更新当前选中的 Tab 索引。

第三步:构建 TabBar 的容器 - tabs.dart

最佳实践是将管理 TabBar 导航的逻辑封装在一个独立的 Widget 中。这有助于保持代码的整洁和可维护性。

lib/pages/ 目录下创建一个新文件 tabs.dart,并添加以下代码:

import 'package:flutter/material.dart'; import 'home.dart'; import 'profile.dart'; // 创建一个有状态的 Widget 来管理我们的 Tabs class Tabs extends StatefulWidget { const Tabs({super.key}); @override State<Tabs> createState() => _TabsState(); } class _TabsState extends State<Tabs> { // 1. 定义一个变量来记录当前选中的 Tab 索引 int _currentIndex = 0; // 2. 创建一个 Widget 列表,用于存放我们想要切换的页面 final List<Widget> _pages = [ const HomePage(), // 首页 const ProfilePage(),// 个人中心页 ]; @override Widget build(BuildContext context) { // 3. 使用 Scaffold 作为页面的根布局 return Scaffold( // 4. body 部分显示当前索引对应的页面 body: _pages[_currentIndex], // 5. 配置底部导航栏 bottomNavigationBar: BottomNavigationBar( // 6. 将当前索引绑定到 navigation bar currentIndex: _currentIndex, // 7. 定义点击事件,当用户点击时更新状态 onTap: (index) { // 使用 setState 来通知 Flutter 框架状态已改变,需要重新渲染 setState(() { _currentIndex = index; }); }, // 当 item 数量大于 3 个时,需要设置此属性以保证样式统一 type: BottomNavigationBarType.fixed, // 8. 定义导航栏中的项目 items: const [ BottomNavigationBarItem( icon: Icon(Icons.home), label: '首页', ), BottomNavigationBarItem( icon: Icon(Icons.person), label: '我的', ), ], ), ); } } 

代码详解:

  • 创建了一个名为 Tabs 的 StatefulWidget
  • 在 _TabsState 中,_currentIndex 是核心状态,它决定了哪个页面应该被显示,哪个标签应该被高亮。
  • _pages 列表将我的页面(HomePage 和 ProfilePage)与索引(0 和 1)对应起来。
  • Scaffold 的 body 属性被设置为 _pages[_currentIndex],这是一个非常巧妙的设计。当我通过 setState 更新 _currentIndex 时,Flutter 会自动重新构建 Scaffold,并根据新的索引从 _pages 列表中取出正确的页面来显示。
  • BottomNavigationBar 的 onTap 回调提供了用户点击的 index,我用它来更新 _currentIndex

第四步:整合到主应用 - 修改 main.dart

现在我已经有了一个功能完备的 Tabs 容器,最后一步就是让我的应用在启动时加载它。

回到 main.dart 文件,进行如下修改:

import 'package:flutter/material.dart'; // 1. 移除不再直接使用的 HomePage 和 ProfilePage 导入 // import 'pages/home.dart'; // import 'pages/profile.dart'; // 2. 引入我们新创建的 Tabs 容器 import 'pages/tabs.dart'; import 'pages/login.dart'; import 'pages/couplet.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.red.shade500), appBarTheme: const AppBarTheme( titleTextStyle: TextStyle( color: Colors.black, fontSize: 18, fontWeight: FontWeight.bold, ), ), ), initialRoute: '/', routes: { // 3. 将应用的根路由 '/' 指向 Tabs Widget '/': (context) => const Tabs(), // 其他独立页面的路由保持不变 '/login': (context) => const LoginPage(), '/couplet': (context) => const CoupletPage(), // 4. HomePage 和 ProfilePage 的路由可以被移除,因为它们已由 Tabs 管理 }, ); } } 

修改解释:
最核心的改动是将根路由 '/' 的目标从 HomePage() 改为了 Tabs()。现在,当应用启动时,它首先加载的是 Tabs Widget。Tabs Widget 内部的 Scaffold 和 BottomNavigationBar 会被构建,并且默认显示 _currentIndex 为 0 对应的页面,也就是 HomePage

效果预览

总结与展望

通过以上步骤,你已经成功地为一个 Flutter 应用实现了核心的 TabBar 主菜单功能。这个结构不仅在 HarmonyOS 上表现出色,在任何支持 Flutter 的平台上都能提供一致的、符合用户习惯的体验。

回顾一下关键点:

  1. 识别需求:认识到独立页面路由无法满足主菜单导航的需求。
  2. 封装容器:创建一个独立的 StatefulWidget (Tabs) 来封装导航逻辑,管理状态和页面切换。
  3. 利用 Scaffold:使用 Scaffold 的 body 和 bottomNavigationBar 属性来构建 UI 结构。
  4. 状态驱动 UI:通过 setState 更新当前选中的 index,驱动 body 内容的切换。
  5. 整合应用:将 MaterialApp 的根路由指向新建的 Tabs 容器。

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

Read more

nginx 部署前端vue项目

nginx 部署前端vue项目

👨‍⚕主页: gis分享者 👨‍⚕感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕收录于专栏:前端工程师 文章目录 * 一、🍓什么是nginx? * 二、🍓nginx 部署前端vue项目步骤 * 2.1 🍉安装nginx * 2.1.1 🍌windows环境安装 * 2.1.2 🍌linux环境安装 * 2.2 🍉打包vue项目 * 2.3 🍉配置nginx 一、🍓什么是nginx? Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡。 优点: * 支持海量高并发:采用IO多路复用epoll。官方测试Nginx能够支持5万并发链接,实际生产环境中可以支撑2-4万并发连接数。 * 内存消耗少 * 可商业化 * 配置文件简单 除了这些优点还有很多,比如反向代理功能,灰度发布,负载均衡功能等

双剑破天门:攻防世界Web题解之独孤九剑心法(七)

双剑破天门:攻防世界Web题解之独孤九剑心法(七)

免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任 **本文以攻防世界部分题为例进行演示,后续会对攻防世界大部分的web题目进行演示,如果你感兴趣请关注** 目录 一:Newscenter 二:upload1 三:Xff_referer 四:Command_execution 五:总结 1. Newscenter(SQL注入) 2. upload1(文件上传漏洞) 3. Xff_referer(HTTP头伪造) 4. Command_execution(命令注入) 一:Newscenter 打开为如下所示 经过尝试,得知在输入框中输入数字可得到不同内容 输入23就没有新闻 所以我们得知这个输入框和数据库有交互,那这题考察的可能就是SQL注入 发现将数据库中所有的内容都查询了出来,那这个题考察的就是SQL注入 字段长度为3 23' order by

目前最流行的 Rust Web 框架是什么?全面对比与选型建议(2026最新版)

Rust 这几年在后端领域的热度持续攀升,从系统编程语言逐渐扩展到 Web 开发领域。很多开发者在学习或选型时都会问: 目前最流行的 Rust Web 框架到底是谁? 今天我们就从生态成熟度、GitHub Star 数量、社区活跃度、性能表现和企业使用情况几个维度,系统分析当前主流 Rust Web 框架。 一、当前最流行的 Rust Web 框架 综合社区活跃度和实际使用情况来看: 目前最流行的 Rust Web 框架是 —— Axum 当然,Actix Web 仍然拥有大量历史用户,而 Rocket 在易用性方面也非常出色。 下面逐个介绍。 🥇 一线框架:Axum(当前热度最高) Axum 是什么? Axum 是基于 Tokio 异步运行时和 Tower 生态构建的现代

【FastapiAdmin V2.0.0】一套现代、开源、全栈融合的中后台快速开发平台,后端采用Fastapi + SQLAlchemy,前端采用基于 Vue3 + Typescript

【FastapiAdmin V2.0.0】一套现代、开源、全栈融合的中后台快速开发平台,后端采用Fastapi + SQLAlchemy,前端采用基于 Vue3 + Typescript

FastapiAdmin v2.0.0 一套现代、开源、全栈融合的中后台快速开发平台,给个⭐️支持一下 📘 项目介绍(作者:@1014TaoTao) FastapiAdmin 是一套 完全开源、高度模块化、技术先进的现代化快速开发平台,旨在帮助开发者高效搭建高质量的企业级中后台系统。该项目采用 前后端分离架构,融合 Python 后端框架 FastAPI 和前端主流框架 Vue3 实现多端统一开发,提供了一站式开箱即用的开发体验。 代码地址: github:https://github.com/1014TaoTao/FastapiAdmin giee:https://gitee.com/tao__tao/FastapiAdmin gitcode: https://gitcode.com/qq_36002987/fastapi_vue3_