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

【鸿蒙原生应用开发实战】第二篇:首页开发——宠物卡片+快捷入口+动态信息流

【鸿蒙原生应用开发实战】第二篇:首页开发——宠物卡片+快捷入口+动态信息流

上一篇我们搭好了项目架子,这一篇开始写真实代码。首页是一个 App 的门面,我们的"萌宠日记"首页包含了宠物切换、快速入口、动态信息流三大模块,麻雀虽小五脏俱全。本文手把手带你实现全部 UI,并讲解 ArkTS 的核心语法。


一、首页整体布局

先看页面结构:

Index.ets ├── 顶部标题栏 (buildHeader) ← "🐾 萌宠日记" + 通知按钮 ├── 宠物卡片区 (buildPetCards) ← 横向滚动 + 选中卡片信息面板 ├── 快捷操作栏 (buildQuickActions) ← 添加宠物/相册/提醒/成长记录 └── 萌宠动态 (buildMoments) ← 动态列表 Feeds

每个模块都是一个@Builder装饰的方法,在build()中按顺序组装。这种组件化拆分的手段,是管理 ArkTS 复杂页面的核心技巧。


二、数据类型定义

在 Index.ets 顶部,我们定义了两个接口:

interfacePet{id:number;name:string;type:string;// 表情符号,如 '🐱'breed:string;// 品种,如 '英短蓝猫'age:string;// 年龄,如 '2岁3个月'avatar:string;weight:string;// 体重,如 '4.5kg'vaccineDate:string;// 最近疫苗日期dewormDate:string;// 最近驱虫日期}interfaceMoment{id:number;petName:string;// 关联宠物名content:string;// 动态内容time:string;// 发布时间描述likes:number;// 点赞数imageCount:number;// 配图数量}

在 ArkTS 严格模式下,所有对象字面量必须有显式类型声明arkts-no-untyped-obj-literals规则)。所以我们在initPets()中初始化数据时,this.pets = [...]的数组元素必须符合Pet接口。


三、问题:首页开发——宠物卡片横向滚动

3.1 宠物头像选择器

这是首页最核心的交互组件——用户通过横向滑动选择宠物,选中后下方显示该宠物的详细信息:

@BuilderbuildPetCards(){Column(){Scroll(){Row(){ForEach(this.pets,(pet:Pet,index?:number)=>{Column(){Stack(){Column().width(68).height(68).borderRadius(34).backgroundColor(this.selectedPetIndex===(indexasnumber)?'#FF6B35':'#F0F0F0')Text(pet.type).fontSize(30)// 显示 🐱/🐶/🐰}.width(68).height(68)Text(pet.name).fontSize(13).fontWeight(FontWeight.Medium).fontColor('#333333')Text(pet.breed).fontSize(10).fontColor('#999999')}.margin({right:16}).onClick(()=>{this.selectedPetIndex=indexasnumber;})},(pet:Pet)=>pet.id.toString())}.padding({left:16})}.scrollable(ScrollDirection.Horizontal).height(120)// ... 下方信息面板}}

关键知识点:

Scroll+ScrollDirection.Horizontal

实现横向滚动的标准组合。Scroll包裹Row,设置scrollable(ScrollDirection.Horizontal),当内容超出屏幕宽度时自动可滑动。

Stack层叠布局

Stack用于将头像圆形背景和 Emoji 叠加在一起。这比用Row+Column更简洁,且支持绝对定位。

选中状态切换

通过selectedPetIndex状态变量和三元表达式动态切换背景色:

.backgroundColor(this.selectedPetIndex===index?'#FF6B35':'#F0F0F0')

3.2 选中宠物的信息面板

点击宠物头像后,下方显示三列信息 + 详情入口:

Row(){Column(){Text(this.pets[this.selectedPetIndex].weight).fontSize(16).fontWeight(FontWeight.Bold).fontColor('#FF6B35')Text('体重').fontSize(10).fontColor('#999999')}.layoutWeight(1).alignItems(HorizontalAlign.Center)Column(){Text(this.pets[this.selectedPetIndex].age).fontSize(16).fontWeight(FontWeight.Bold).fontColor('#3498DB')Text('年龄')}.layoutWeight(1).alignItems(HorizontalAlign.Center)// ... 品种列Column(){Text('详情>').fontSize(12).fontColor('#FF6B35')}.layoutWeight(1).alignItems(HorizontalAlign.Center).onClick(()=>{router.pushUrl({url:'pages/PetDetailPage',params:{petId:this.pets[this.selectedPetIndex].id}});})}.width('100%').padding(12).backgroundColor('#FFFFFF').borderRadius(10)

知识点:layoutWeight(1)实现等分

layoutWeight(1)让四个 Column 平分 Row 的宽度,比写死百分比更灵活。这是 ArkUI 中实现等分布局的推荐做法。


四、快捷操作栏

四个功能入口整齐排列:

@BuilderbuildQuickActions(){Row(){Column(){Text('➕').fontSize(22)Text('添加宠物').fontSize(11).fontColor('#666666')}.layoutWeight(1).alignItems(HorizontalAlign.Center).onClick(()=>router.pushUrl({url:'pages/AddPetPage'}))Column(){Text('📷').fontSize(22)Text('相册').fontSize(11).fontColor('#666666')}.layoutWeight(1).alignItems(HorizontalAlign.Center).onClick(()=>router.pushUrl({url:'pages/AlbumPage'}))Column(){Text('💉').fontSize(22)Text('提醒').fontSize(11).fontColor('#666666')}.layoutWeight(1).alignItems(HorizontalAlign.Center).onClick(()=>router.pushUrl({url:'pages/ReminderPage'}))Column(){Text('📊').fontSize(22)Text('成长记录').fontSize(11).fontColor('#666666')}.layoutWeight(1).alignItems(HorizontalAlign.Center).onClick(()=>router.pushUrl({url:'pages/PetDetailPage',params:{petId:...}}))}.width('100%').padding(14).backgroundColor('#FFFFFF').margin({top:12,left:16,right:16}).borderRadius(12)}

这里有一个有意思的设计细节:四个入口中,"添加宠物"和"成长记录"跳转到不同页面,但"成长记录"复用了PetDetailPage(通过 params 传参区分)。这种页面复用的策略可以减少页面数量,保持路由简洁。


五、萌宠动态信息流

5.1 动态列表渲染

@BuilderbuildMoments(){Column(){Row(){Text('📝 萌宠动态').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#1A1A2E')Blank()Text(`${this.moments.length}`).fontSize(12).fontColor('#999999')}.width('100%').padding({left:16,right:16,top:16})ForEach(this.moments,(moment:Moment)=>{Column(){// 头部:头像 + 名字 + 时间Row(){Stack(){Column().width(36).height(36).borderRadius(18).backgroundColor('#FFE0D0')Text(moment.petName==='团子'?'🐱':moment.petName==='豆豆'?'🐶':'🐰').fontSize(18)}Column(){Text(moment.petName).fontSize(14).fontWeight(FontWeight.Medium)Text(moment.time).fontSize(10).fontColor('#BBBBBB')}.margin({left:8}).layoutWeight(1)Text('···').fontSize(14).fontColor('#CCCCCC')}.width('100%')// 正文Text(moment.content).fontSize(13).fontColor('#666666').lineHeight(20).width('100%').margin({top:8})// 配图占位(有图才显示)if(moment.imageCount>0){Row(){ForEach([1,2,3],(i:number)=>{if(i<=moment.imageCount){Column().width(80).height(80).backgroundColor('#F0F0F0').borderRadius(6).margin({right:6})}},(i:number)=>i.toString())}.width('100%').margin({top:6}).height(80)}// 底部互动:点赞 + 评论Row(){Blank()Text(`❤️${moment.likes}`).fontSize(12).fontColor('#999999').margin({left:12})Text('💬 评论').fontSize(12).fontColor('#999999').margin({left:12})}.width('100%').margin({top:6})}.width('100%').padding(14).backgroundColor('#FFFFFF').borderRadius(10).margin({top:8,left:16,right:16}).alignItems(HorizontalAlign.Start)},(moment:Moment)=>moment.id.toString())}.width('100%')}

5.2 ForEach 的关键参数

ForEach的第三个参数是键值生成器,用于追踪列表项的增删改:

ForEach(this.moments,// 数据源(moment:Moment)=>{...},// UI 模板(moment:Moment)=>moment.id.toString()// key 生成器)

为什么要传 key?

  • 提升 diff 更新性能
  • 避免列表项重排时 UI 闪烁
  • 符合 ArkTS 的渲染优化要求

5.3 条件渲染的优雅写法

配图区域只在moment.imageCount > 0时才渲染:

if(moment.imageCount>0){Row(){/* 图片占位 */}}

这是 ArkTS 中条件渲染的标准写法。不需要v-if*ngIf,直接用if语句。


六、@State 装饰器与响应式编程

整个首页的核心状态只有三个变量:

@Statepets:Pet[]=[];// 宠物列表@Statemoments:Moment[]=[];// 动态列表@StateselectedPetIndex:number=0;// 选中的宠物索引

@State是 ArkTS 响应式系统的基石:

特性说明
自动追踪@State变量被读取时自动记录依赖
精准更新变量变化时只重新渲染依赖它的组件
不可变替换数组/对象需要整体替换而非修改属性

注意:@State只能装饰属于组件自身的状态,如果状态需要跨组件共享,需要使用@Prop@Link@Provide/@Consume


七、UI 设计技巧总结

7.1 颜色系统

我们定义了一套隐式的色彩规范:

用途色值使用场景
主色调#FF6B35选中状态、按钮、链接
深色文字#333333标题、正文
灰色文字#999999辅助信息、说明
浅灰文字#BBBBBB时间戳、次要信息
页面背景#F5F5F5整体背景色
卡片背景#FFFFFF所有卡片

7.2 卡片阴影与圆角

所有卡片统一风格:

.backgroundColor('#FFFFFF').borderRadius(10)// 圆角.margin({top:8,left:16,right:16})

虽然没有显式加阴影,但白色卡片在浅灰背景上已经产生视觉层次感。需要阴影时可以用.shadow()方法。

7.3 Emoji 的妙用

全篇大量使用了 Emoji 作为图标:

场景Emoji
宠物类型🐱 🐶 🐰
快捷入口➕ 📷 💉 📊
动态互动❤️ 💬
通知按钮🔔

这样做的好处是零资源开销——不需要引入任何图标库或图片资源,一个 Unicode 字符搞定。对小型应用来说,这是性价比最高的 UI 方案。


八、完整 build() 组装

build():void{Column(){this.buildHeader()// 顶部标题栏Scroll(){Column(){this.buildPetCards()// 宠物卡片this.buildQuickActions()// 快捷操作this.buildMoments()// 动态信息流}.width('100%').padding({bottom:20})}.scrollable(ScrollDirection.Vertical).layoutWeight(1).width('100%')}.width('100%').height('100%').backgroundColor('#F5F5F5')}

整个页面被包裹在一个Column中,其中Scroll占满剩余空间(layoutWeight(1)),内部再嵌套Column按顺序排列三个模块。

这种垂直滚动 + 横向子滚动的嵌套结构,是移动端首页最经典的布局模式。


九、知识点串讲

知识点本页示例
@Builder方法拆分4个 Builder 分别对应4个 UI 区块
@State响应式变量pets, moments, selectedPetIndex
Scroll双向滚动纵向整页 + 横向宠物卡片
ForEach列表渲染宠物列表 + 动态列表
Stack层叠布局圆形头像背景 + Emoji
layoutWeight等分快捷入口四等分
if条件渲染配图区域的显示/隐藏
router.pushUrl跳转到详情/添加/相册/提醒页

十、下篇预告

下一篇我们做添加宠物页面 + 宠物详情页

  • TextInput 表单的完整实现
  • 标签选择器(宠物类型/性别)
  • 三个 Tab 页签切换(健康档案/体重记录/疫苗记录)
  • 柱状图式体重趋势展示

敬请期待!🚀


系列导航:

  • 第一篇:项目搭建与架构
  • 第二篇:首页开发(本文)
  • 第三篇:表单与详情页
  • 第四篇:相册与提醒功能
  • 第五篇:总结与最佳实践
http://www.jsqmd.com/news/1002599/

相关文章:

  • 2026年6月德州企业车拖车服务贴心推荐指南:如何构建高效的车辆应急保障体系 - 品牌鉴赏官2026
  • 草本头疗到底怎么样?一人一方针对护理
  • 2026年中济南地区值得信赖的氨基磺酸实力生产供应商深度解析 - 品牌鉴赏官2026
  • 2026年6月施耐德电气实力厂家口碑推荐,工控产品/电气自动化/中低压电气/施耐德电气,施耐德电气供应商推荐 - 品牌推荐师
  • 2026年 锯条/碳钢锯条/合金锯条厂家推荐:南通高铁配件与纺织配件厂商实力口碑之选 - 品牌发掘
  • AI 辅助的 Flutter 动画曲线智能推荐:从用户感知到参数搜索的工程方案
  • 告别Windows思维:在EAIDK-610的Linux上用Vim和GDB调试你的第一个C++程序
  • 2026甄选:东莞市茂立洁科技有限公司——研磨盘领域的专业制造厂家 - 品牌发掘
  • 高数期末救命!72道不定积分题里,这5类换元法套路最常考
  • OpenCV找圆心翻车实录:光照不均、部分遮挡的圆怎么破?我的踩坑与调参经验
  • SpaceX 750 亿美元 IPO 估值达 1.77 万亿美元,马斯克距万亿身家仅一步之遥
  • 基于主题建模的心理量表简化方法研究
  • OpenAI营销权一分为二,B2B老将Fleming上任,能否破局企业市场混战?
  • 2026靠谱降AI率平台怎么选?实测15款后这几个最实用
  • Obsidian Better Export PDF插件:解锁高效批量导出与专业PDF生成
  • SPSS多因素方差分析保姆级教程:从数据导入到交互作用图,手把手搞定广告效果评估案例
  • SQL 查询终极高阶通鉴:从零基础拆解到工业级多表联查、窗口函数与索引优化
  • 如何高效优化Windows系统:免费工具Dism++的专业使用指南
  • 2026年四川变压器回收公司服务能力对比:哪些企业值得关注? - 优质品牌商家
  • 2026年6月大件物流厂家推荐,大件物流/大件运输,大件物流公司口碑推荐 - 品牌推荐师
  • 在西安换ECO棉床垫,大家有靠谱的店推荐吗? - 深圳市民HLL
  • 前端焦点管理与键盘导航:从 Tab 顺序到无障碍交互的工程实践
  • NSK W4509SA-1Z-C5Z10 滚珠丝杠详解
  • I3C总线端口扩展利器:P3S0200高速开关的设计与应用
  • STM32F103C8T6软件SPI驱动MAX6675读取热电偶温度(附完整代码与焊接避坑指南)
  • 当法理介入情场:家理律师入驻《爱情保卫战》,重构情感调解的理性坐标 - 外贸老黄
  • 哇塞!原来毕业论文有这操作?2026降AIGC网站推荐合集
  • 2026成都别墅设计公司怎么挑?从行业视角看8家企业的差异化实力 - 优质品牌商家
  • 2026年石墨接地线品牌怎么选?基于技术、案例与交付能力的行业研究分析 - 优质品牌商家
  • 2026实力厂家:聊城六角钢管品牌与精密工艺全览 - 企业推荐官【官方】