当前位置: 首页 > news >正文

07-Flutter鸿蒙页面开发基础:路由、底部导航和常用组件

07. Flutter鸿蒙页面开发基础:路由、底部导航和常用组件

项目跑起来后,就可以开始写 Flutter 页面。入门阶段不需要马上引入复杂状态管理,先把入口、页面拆分、底部导航、列表、详情页和通用组件写清楚,就能支撑大多数小型业务页面。

页面目录

推荐目录:

lib ├─ main.dart ├─ app.dart ├─ pages │ ├─ home_page.dart │ ├─ list_page.dart │ ├─ detail_page.dart │ └─ profile_page.dart └─ widgets └─ feature_card.dart

App 入口

import'package:flutter/material.dart';import'pages/home_page.dart';voidmain(){runApp(constDemoApp());}classDemoAppextendsStatelessWidget{constDemoApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnMaterialApp(debugShowCheckedModeBanner:false,title:'Flutter Ohos Demo',theme:ThemeData(colorSchemeSeed:Colors.blue,useMaterial3:true,),home:constHomePage(),);}}

底部导航

classHomePageextendsStatefulWidget{constHomePage({super.key});@overrideState<HomePage>createState()=>_HomePageState();}class_HomePageStateextendsState<HomePage>{int _index=0;finalList<Widget>_pages=const[Center(child:Text('首页')),Center(child:Text('列表')),Center(child:Text('我的')),];@overrideWidgetbuild(BuildContextcontext){returnScaffold(body:_pages[_index],bottomNavigationBar:NavigationBar(selectedIndex:_index,onDestinationSelected:(value){setState(()=>_index=value);},destinations:const[NavigationDestination(icon:Icon(Icons.home_outlined),label:'首页'),NavigationDestination(icon:Icon(Icons.list_alt),label:'列表'),NavigationDestination(icon:Icon(Icons.person_outline),label:'我的'),],),);}}

列表与详情

classDemoListPageextendsStatelessWidget{constDemoListPage({super.key});@overrideWidgetbuild(BuildContextcontext){finalitems=List.generate(20,(index)=>'第${index+1}条内容');returnListView.separated(padding:constEdgeInsets.all(16),itemCount:items.length,separatorBuilder:(_,__)=>constSizedBox(height:10),itemBuilder:(context,index){returnListTile(shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(12)),tileColor:Colors.blue.withOpacity(0.08),title:Text(items[index]),trailing:constIcon(Icons.chevron_right),onTap:(){Navigator.of(context).push(MaterialPageRoute(builder:(_)=>DetailPage(title:items[index]),),);},);},);}}classDetailPageextendsStatelessWidget{finalStringtitle;constDetailPage({super.key,requiredthis.title});@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text(title)),body:Center(child:Text('详情内容:$title')),);}}

组件拆分

页面稳定后,把重复 UI 抽成组件:

classFeatureCardextendsStatelessWidget{finalIconDataicon;finalStringtitle;finalStringdesc;finalVoidCallback?onTap;constFeatureCard({super.key,requiredthis.icon,requiredthis.title,requiredthis.desc,this.onTap,});@overrideWidgetbuild(BuildContextcontext){returnInkWell(borderRadius:BorderRadius.circular(14),onTap:onTap,child:Container(padding:constEdgeInsets.all(16),decoration:BoxDecoration(color:Colors.white,borderRadius:BorderRadius.circular(14),border:Border.all(color:Colors.black12),),child:Row(children:[Icon(icon,size:32,color:Colors.blue),constSizedBox(width:12),Expanded(child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text(title,style:constTextStyle(fontSize:17,fontWeight:FontWeight.w600)),constSizedBox(height:4),Text(desc,style:constTextStyle(color:Colors.black54)),],),),],),),);}}

页面状态不要散落在多个地方

页面简单时可以用setState,但状态变量要集中管理。例如底部导航只维护一个_index,列表页只维护自己的加载状态。不要在父页面和子页面里同时维护相同状态,否则刷新时容易不一致。

classPageState<T>{finalbool loading;finalT?data;finalObject?error;constPageState({this.loading=false,this.data,this.error,});}

这个小类可以让页面状态更清楚:加载中、成功、失败分别对应不同字段。

页面尺寸适配

鸿蒙设备可能有不同尺寸,布局时尽量少写死宽度。优先使用:

LayoutBuilder(builder:(context,constraints){finalcompact=constraints.maxWidth<420;returnPadding(padding:EdgeInsets.all(compact?12:20),child:constText('自适应内容'),);},)

这样页面在手机、折叠屏或平板场景下更容易继续扩展。
(context, constraints) {
final compact = constraints.maxWidth < 420;
return Padding(
padding: EdgeInsets.all(compact ? 12 : 20),
child: const Text(‘自适应内容’),
);
},
)

这样页面在手机、折叠屏或平板场景下更容易继续扩展。
http://www.jsqmd.com/news/1175775/

相关文章:

  • CCFrank4dblp数据更新机制:如何确保会议期刊等级实时准确? [特殊字符]
  • AI应用的可观测性:LLM调用的全链路追踪与异常诊断平台
  • Gitee 分支模型实战:从Master到Release的5种分支策略与命名规范
  • 2026工业烘干除湿一体机资质齐全品牌排行梳理 - 互联网科技品牌测评
  • H5F从入门到放弃?完整学习路径助你成为表单验证专家
  • 2026中山新能源维修哪家靠谱 服务商客观对比参考 - 互联网科技品牌测评
  • 从施工覆盖到售后维保,看西安豪美家装施工与售后服务 - 子柔传媒
  • 亨得利官方名表服务中心|网点地址与24小时热线权威信息通告(2026年7月更新) - 亨得利官方博客
  • ChatGPT写问卷的3大致命误区:92%的团队踩坑在第2步(附诊断自查表+修正前后回收率对比)
  • 终极视觉文档检索解决方案:NVIDIA Llama-Nemotron-Colembed-VL-3B-V2深度解析
  • Proteus:如何从Go代码快速生成Protocol Buffers文件的终极指南
  • 串口UART,IIC,SPI三者的介绍和区别
  • Spekt8核心功能揭秘:Pod状态监控、服务依赖分析与资源消耗统计
  • MaterialValues颜色系统深度解析:500+颜色资源使用指南
  • 前端 AI 工具链的评测体系:精度、延迟和开发者体验的三维度量
  • 永磁同步电机无感控制:电压电流互补混合磁链观测器的解析与实现
  • 鸿蒙 构建系统:构建任务(三)
  • 2026工业烘干除湿一体机哪家资质全排行盘点 - 互联网科技品牌测评
  • 深度解析:如何将老旧电视盒子转化为专业服务器的技术方案
  • STM32与TPS61170实现高效DC-DC升压方案
  • Prism 框架 入门
  • 抖店爆单订单自动化完整解决方案(2026合规密文版,抖掌柜适配单店/店群千单量级) - 抖掌柜
  • 最新实测广州各大连锁钻铺,7 月行情同步实时钻石流通报价 - 每日生活报
  • ReadCat小说阅读器:3分钟掌握免费开源的跨平台阅读神器终极解决方案
  • 如何在Mac上部署Agents-A1-bf16?超简单MLX框架环境搭建指南
  • 2026年消失模白膜烘干设备主流品牌排行一览 - 互联网科技品牌测评
  • 08 Spring 循环依赖怎么解决的?你背了三级缓存,但面试官其实想听这句
  • Rust 错误处理最佳实践清单:从库到应用的一整套约定
  • 医疗信创实战|全栈国产化改造与金仓数据库应用实践
  • 小实验-MPLS VPN Option C2(锐捷设备)