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

鸿蒙原生应用实战(二):首页与诗词库页面开发——多元布局与交互实现

鸿蒙原生应用实战(二):首页与诗词库页面开发——多元布局与交互实现

前言

在上一章中,我们完成了项目初始化和架构设计。本章将正式进入编码阶段,集中开发应用的两个核心页面:

  1. 首页(Index.ets)—— 信息聚合入口
  2. 诗词库(PoemListPage.ets)—— 搜索与筛选

这两个页面涉及了大量 ArkTS 布局技巧、组件复用和数据绑定模式,是鸿蒙开发的核心实战内容。

一、首页开发(Index.ets)

1.1 页面布局总览

首页从上到下分为五个区域:

┌──────────────────────┐ │ 标题栏 + 用户头像 │ ← Row + Column 组合 ├──────────────────────┤ │ 每日诗词推荐卡片 │ ← 渐变背景 + 引用样式 ├──────────────────────┤ │ 6 大分类入口 (Grid) │ ← 2 行 3 列网格 ├──────────────────────┤ │ 热门排行列表 │ ← 带序号和点赞数 ├──────────────────────┤ │ 为你推荐列表 │ ← 与排行相同结构 ├──────────────────────┤ │ 底部导航栏 │ ← 4 个 Tab └──────────────────────┘

1.2 数据结构定义

在 ArkTS 的严格模式下,所有对象字面量必须有显式类型声明

// 诗词条目接口interfacePoemItem{id:number;title:string;author:string;dynasty:string;content:string[];// 诗句数组type:string;// 五言绝句 / 词 / 乐府 ...likes:number;}// 每日推荐数据constdailyPoem:DailyPoem={title:'定风波',author:'苏轼',dynasty:'宋',excerpt:'竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。'};// 热门排行数据consttopPoems:PoemItem[]=[{id:1,title:'静夜思',author:'李白',dynasty:'唐',content:['床前明月光','疑是地上霜','举头望明月','低头思故乡'],type:'五言绝句',likes:9852},// ... 更多诗词];

1.3 渐变背景卡片(每日诗词)

首页最醒目的"每日一首"卡片使用了渐变背景效果。在 ArkTS 中,可以通过background属性实现:

Column(){Text('每日一首').fontSize(12).fontColor('rgba(255,255,255,0.7)').width('100%')Text(dailyPoem.title).fontSize(22).fontWeight(FontWeight.Bold).fontColor(Color.White).width('100%').padding({top:8})Text('—— '+dailyPoem.dynasty+'·'+dailyPoem.author).fontSize(13).fontColor('rgba(255,255,255,0.8)').width('100%')// 居中展示经典名句Text(dailyPoem.excerpt).fontSize(17).fontColor(Color.White).lineHeight(28).textAlign(TextAlign.Center).padding({top:16,bottom:8})}.width('100%').padding(20)// 渐变色背景——紫色系渐变.background('linear-gradient(135deg, #667eea, #764ba2)').borderRadius(16)

技巧linear-gradient是 ArkTS 支持的背景渐变语法,适合做卡片头部装饰。

1.4 网格布局(6 大分类)

使用Grid组件实现 2 行 3 列的诗词分类入口:

Grid(){ForEach(categories,(cat:string)=>{GridItem(){this.createCategoryCard(cat)}},(cat:string)=>cat)}.columnsTemplate('1fr 1fr 1fr')// 3列等宽.rowsTemplate('1fr 1fr')// 2行.rowsGap(12).columnsGap(12).width('100%')

每个分类卡片包含 emoji 图标和文字标签,点击后跳转到诗词库页面并自动筛选该分类。

1.5 @Builder 组件复用

在 ArkTS 中,@Builder组件复用的核心机制。需要注意一个关键限制:@Builder 内不能声明变量

// ❌ 错误——@Builder 内不能有 const/interface@BuildercreateCategoryCard(name:string){consticons:Record<string,string>={...};// 编译报错!// ...}// ✅ 正确——将数据提取为普通方法getCatIcon(name:string):string{consticons:Record<string,string>={'唐诗三百':'📜','宋词精选':'🌸','元曲':'🎭','古诗十九首':'📖','乐府诗集':'🎵','诗经':'📗'};returnicons[name]||'📜';}@BuildercreateCategoryCard(name:string){Column(){Text(this.getCatIcon(name)).fontSize(28)Text(name).fontSize(12).fontColor($r('app.color.text_primary')).margin({top:8}).fontWeight(FontWeight.Medium)}// ...}

1.6 图片圆形容器

首页右上角的用户头像使用了Circle组件 +.overlay()的组合:

Circle().width(40).height(40).fill($r('app.color.accent_purple')).overlay(this.avatarText())

overlay是一个@Builder 方法

@BuilderavatarText(){Text('诗').fontColor(Color.White).fontSize(18).fontWeight(FontWeight.Bold)}

注意:在早期版本的 ArkTS 中,.overlay()不能直接接受Text()组件,必须通过@Builder方法包装。

二、诗词库页面开发(PoemListPage.ets)

2.1 交互功能概览

诗词库页面是用户浏览诗词的核心入口,包含三个维度:

交互维度实现方式数据来源
搜索TextInput组件用户输入,实时过滤
朝代筛选标签按钮 Row6 个选项(全部/先秦/唐/五代/宋/元)
类型筛选标签按钮 Row5 个选项(全部/五绝/七律/词/乐府)

2.2 数据过滤逻辑

之前我们使用了get filteredPoems()访问器,但在运行时发现其在模板中会返回undefined

// ❌ 不可行——get 访问器在模板返回 undefinedgetfilteredPoems():PoemItem[]{// ...过滤逻辑returnresult;// 运行时始终 undefined!}

正确做法:使用@State+@Watch组合:

@State@Watch('onFilterChange')searchText:string='';@State@Watch('onFilterChange')activeDynasty:string='all';@State@Watch('onFilterChange')activeType:string='all';@StatefilteredList:PoemItem[]=allPoems;// 存储过滤结果onFilterChange():void{letresult:PoemItem[]=allPoems;if(this.searchText.length>0){constkeyword:string=this.searchText.toLowerCase();result=result.filter((p:PoemItem)=>p.title.includes(keyword)||p.author.includes(keyword));}if(this.activeDynasty!=='all'){result=result.filter((p:PoemItem)=>p.dynasty===this.activeDynasty);}if(this.activeType!=='all'){result=result.filter((p:PoemItem)=>p.type===this.activeType);}this.filteredList=result;// 更新状态触发重新渲染}

工作原理:当searchTextactiveDynastyactiveType任一状态变化时,@Watch('onFilterChange')自动触发onFilterChange()方法,更新filteredList,UI 随之刷新。

2.3 搜索框实现

TextInput是鸿蒙中的文本输入组件:

Row(){Text('🔍').fontSize(16).margin({left:12})TextInput({placeholder:'搜索诗词名称或作者...',text:this.searchText}).layoutWeight(1).backgroundColor(Color.Transparent).fontSize(14).placeholderColor($r('app.color.text_secondary')).onChange((val:string)=>{this.searchText=val;})// 搜索框不为空时显示清除按钮if(this.searchText.length>0){Text('✕').fontSize(16).fontColor($r('app.color.text_secondary')).margin({right:12}).onClick(()=>{this.searchText='';})}}.width('100%').height(44).backgroundColor($r('app.color.bg_card')).borderRadius(22)// 圆角搜索框

2.4 筛选标签

筛选标签的样式逻辑:选中的标签用主题色填充,未选中的用白色:

Text(filter.label).fontSize(13).fontColor(filter.name===this.activeDynasty?Color.White:$r('app.color.text_secondary')).padding({left:14,right:14,top:6,bottom:6}).backgroundColor(filter.name===this.activeDynasty?$r('app.color.accent_purple'):$r('app.color.bg_card')).borderRadius(16).onClick(()=>{this.activeDynasty=filter.name;})

2.5 结果计数与空状态

// 结果计数Row(){Text('共 '+this.filteredList.length+' 首').fontSize(12).fontColor($r('app.color.text_secondary'))Blank()}// 空状态展示if(this.filteredList.length===0){Column(){Text('📖').fontSize(48)Text('没有找到相关诗词').fontSize(16).fontColor($r('app.color.text_secondary')).margin({top:12})}.width('100%').height(200).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)}

2.6 卡片列表

每条诗词卡片显示:序号、标题、类型标签、朝代·作者、诗文节选、点赞数:

@BuildercreatePoemCard(poem:PoemItem){Row(){// 序号Text(poem.id.toString()).fontSize(22).fontWeight(FontWeight.Bold).fontColor($r('app.color.accent_purple')).opacity(0.3)Column(){Row(){Text(poem.title).fontSize(17).fontWeight(FontWeight.Bold)Text(poem.type).fontSize(10).fontColor($r('app.color.accent_purple')).padding({left:6,right:6,top:2,bottom:2}).backgroundColor($r('app.color.accent_purple')+'15').borderRadius(4)}Text(poem.dynasty+' · '+poem.author).fontSize(13).fontColor($r('app.color.text_secondary'))// 诗文节选(最多两行)Text(poem.content[0]+(poem.content.length>1?','+poem.content[1]:'')).fontSize(14).fontColor($r('app.color.text_secondary')).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})Text('❤ '+poem.likes.toString()).fontSize(12).fontColor($r('app.color.accent_red'))}}.width('100%').padding(14).backgroundColor($r('app.color.bg_card')).borderRadius(12).onClick(()=>{router.pushUrl({url:'pages/PoemDetailPage',params:{poemId:poem.id}});})}

三、跨页面参数传递

3.1 从作者页跳转到诗词库并搜索

AuthorPage点击诗人卡片后,会跳转到诗词库并自动填入作者名进行搜索:

// AuthorPage.ets.onClick(()=>{router.pushUrl({url:'pages/PoemListPage',params:{searchAuthor:author.name}});})// PoemListPage.ets — 接收参数aboutToAppear():void{constparams=router.getParams()asRecord<string,Object>;if(params&&params['searchAuthor']!==undefined){this.searchText=params['searchAuthor']asstring;// @Watch 会自动触发 onFilterChange,更新 filteredList}}

四、@Builder 中的 if 条件

在 ArkTS 中,if条件语句可以直接在build()@Builder中使用:

@BuildercreatePoemCard(poem:PoemItem){Row(){if(this.editMode){Circle()// 编辑模式下的选择框.width(22).height(22).stroke($r('app.color.accent_purple')).strokeWidth(2).fill(Color.Transparent)}// ... 其余内容}}

但需要注意:if条件内部只能包含 UI 组件语法,不能包含变量声明、函数调用赋值等。

小结

本章完成了首页和诗词库两个核心页面的开发,涵盖了:

  • 渐变背景卡片的设计
  • Grid 网格布局的使用
  • @Builder 组件复用技巧
  • 搜索 + 双维度筛选的实现
  • 跨页面参数传递
  • 数据过滤的最佳实践(@State + @Watch)

在下一章中,我们将继续开发诗词详情和作者天地两个页面,深入复杂数据展示和交互设计。


【系列目录】

  • (一)项目初始化与架构设计
  • (二)首页与诗词库页面开发 ← 本文
  • (三)诗词详情与作者天地页面开发
  • (四)收藏页面与底部导航实现
  • (五)编译调试与问题修复经验
http://www.zskr.cn/news/1487173.html

相关文章:

  • 对话式辅助系统设计:从问答管道到任务操作系统的范式迁移
  • 抚顺市黄金回收白银回收铂金回收哪里靠谱?2026 实测 5 家正规实体门店推荐 - 中业金奢再生回收中心
  • 第 06 篇:企业数据源安全连接 —— 让 AI 安全地访问你的数据
  • S32G串行引导机制解析:从BootROM协议到UART/CAN实战
  • 如何通过InteractiveHtmlBom插件创建专业级PCB交互式物料清单
  • 百万Token看着香,但你的场景真的需要吗?
  • Teamcenter许可优化,5款自动化工具
  • 大理黄金回收白银回收铂金回收实测 + 5 家正规线下门店盘点 - 信誉隆金银铂奢回收
  • OpCore-Simplify:基于智能分析的自动化OpenCore EFI配置方案
  • MPC7450指令流水线优化:指令对齐、分支预测与资源管理实战
  • PN7160动态功率控制(DPC)原理与实战:从天线调谐到射频合规性优化
  • ChanlunX:通达信缠论智能分析插件,3步实现股票走势自动化识别
  • 河北58处国控地表水监测断面精确坐标数据(含市县、河流、流域信息)
  • PMSM无感FOC控制实战包:Simulink建模→滑模观测器→IF启动→dsPIC33实测全流程
  • 如何用AI在3分钟内制作专业短视频:Pixelle-Video终极指南
  • MonkeyCode 与国产大模型:通义千问、DeepSeek、GLM的适配之路
  • 免费视频去水印在线工具有哪些?实测推荐,免费视频去水印在线工具怎么选? - 工具软件使用方法推荐
  • 避坑指南:手把手教你搞定宝兰德BES 9.5.2单实例的分离安装与控制台访问
  • 影刀RPA多店铺跨店营销实战:统一满减活动配置与跨店订单自动分账系统
  • STM32F407 USB高速设备开发全套资源:KEIL工程+Windows驱动+CDC/MSC/HID示例
  • 生成式音频:从TTS到语义驱动的多模态声音生成
  • 影刀RPA多店铺商品素材中心与批量处理自动化实战
  • 12个开源组件:构建你的智能知识管理系统
  • Defender Control终极指南:3步永久禁用Windows Defender的完整教程
  • MonkeyCode 开源安全审计:第三方依赖风险管理与供应链安全
  • 深入解析DCm2 TPU函数集:直流电机PWM控制与同步信号生成
  • imageio-ffmpeg:Python 视频处理的轻量封装
  • 增城及全城爱宠人士请查收!纯种猫咪狗狗现货,可上门挑选,就在广州黎宥萌宠生活馆 - 润富黄金回收
  • 如何在5分钟内掌握B站视频下载神器DownKyi:新手快速上手终极指南
  • 2026合肥管道疏通公司最新服务测评推荐,只选靠谱商家,我们一起避坑,少花钱! - 极速版本