HarmonyOS应用开发实战:萌宠日记 - 时间轴筛选与排序功能
HarmonyOS应用开发实战萌宠日记 - 时间轴筛选与排序功能前言筛选与排序是时间轴列表的进阶功能它帮助用户按不同维度查看成长事件。在萌宠日记的GrowthTimelinePage中顶部有一个筛选按钮▽点击后可弹出筛选面板提供按时间排序、按类型筛选、只看特殊事件等选项让用户灵活地浏览成长记录。本文将从萌宠日记时间轴筛选功能的实现出发深入解析筛选按钮设计、排序逻辑、数据过滤、筛选面板 UI以及筛选状态的 UI 反馈。一、筛选功能整体架构1.1 功能需求功能说明优先级按日期排序正向/反向排序P0按年龄排序按年龄大小排序P1只看特殊事件只显示生日等特殊事件P0按年份筛选选择特定年份的事件P2重置筛选恢复默认显示P01.2 数据流用户点击筛选按钮 → 弹出筛选面板 → 选择筛选条件 ↓ 更新 State 筛选状态 → 触发计算属性重新计算 ↓ sortedData 返回过滤后的数据 → UI 自动更新 ↓ 时间轴列表重新渲染二、筛选按钮设计2.1 筛选按钮实现// GrowthTimelinePage.ets — 筛选按钮 Row() { Blank() Text(▽) .fontSize(16) .fontColor(#666666) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .backgroundColor(#F5F5F5) .borderRadius(16) .onClick(() { this.showFilterOptions() }) } .width(100%) .padding({ right: 16, top: 8 })2.2 按钮样式参数参数值说明图标▽向下箭头暗示可展开字号16fp适中大小颜色#666666灰色背景色#F5F5F5浅灰背景圆角16vp胶囊形位置右上角不遮挡内容三、排序筛选逻辑3.1 排序选项State sortBy: date | age date State filterSpecial: boolean false State filterYear: string all // 排序后的数据 get sortedData(): TimelineItem[] { let data [...this.timelineData] // 按年份筛选 if (this.filterYear ! all) { data data.filter(item item.date.startsWith(this.filterYear)) } // 只看特殊事件 if (this.filterSpecial) { data data.filter(item item.isSpecial) } // 排序 data.sort((a, b) { if (this.sortBy date) { return b.date.localeCompare(a.date) // 按日期降序 } else { return b.age.localeCompare(a.age) // 按年龄降序 } }) return data }3.2 排序方式对比排序方式排序字段效果适用场景按日期降序date最新事件在前默认按日期升序date反转最早事件在前回顾按年龄降序age最近事件在前查看成长四、筛选面板实现4.1 筛选面板 UIState showFilterPanel: boolean false showFilterOptions(): void { this.showFilterPanel !this.showFilterPanel } // 筛选面板 if (this.showFilterPanel) { Column({ space: 12 }) { Text(筛选排序) .fontSize(16).fontWeight(FontWeight.Bold) // 排序方式 Text(排序方式).fontSize(14).fontColor(#999999) Row({ space: 8 }) { Text(按日期) .fontSize(13) .fontColor(this.sortBy date ? #FFFFFF : #666666) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .backgroundColor(this.sortBy date ? #F5A623 : #F5F5F5) .borderRadius(16) .onClick(() { this.sortBy date }) Text(按年龄) .fontSize(13) .fontColor(this.sortBy age ? #FFFFFF : #666666) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .backgroundColor(this.sortBy age ? #F5A623 : #F5F5F5) .borderRadius(16) .onClick(() { this.sortBy age }) } // 只看特殊事件 Row() { Text(只看特殊事件).fontSize(14) Blank() Toggle({ type: ToggleType.Switch, isOn: this.filterSpecial }) .onChange((v) { this.filterSpecial v }) } // 重置按钮 Button(重置) .width(100%).height(36) .fontColor(#F5A623).backgroundColor(#FFF3E0) .borderRadius(18) .onClick(() { this.sortBy date this.filterSpecial false this.filterYear all }) } .width(100%).padding(16) .backgroundColor(#FFFFFF).borderRadius(16) .shadow({ radius: 8, color: #20000000, offsetY: 4 }) }五、筛选状态指示5.1 激活状态// 筛选激活时按钮高亮 get isFilterActive(): boolean { return this.sortBy ! date || this.filterSpecial || this.filterYear ! all } Text(▽) .fontSize(16) .fontColor(this.isFilterActive ? #F5A623 : #666666) .backgroundColor(this.isFilterActive ? #FFF3E0 : #F5F5F5) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .borderRadius(16)六、筛选结果统计6.1 结果数量// 显示筛选后的结果数量 Text(共 ${this.sortedData.length} 条记录) .fontSize(12).fontColor(#999999) .padding({ right: 16 })七、筛选与列表的联动7.1 数据绑定// 使用 sortedData 作为列表数据源 List({ space: 0 }) { ForEach(this.sortedData, (item: TimelineItem, index: number) { ListItem() { this.TimelineItemView(item, index) } }) }八、筛选的持久化8.1 保存筛选偏好// 保存筛选偏好到 Preferences async saveFilterPreferences(): Promisevoid { const pref await preferences.getPreferences(this.context, timeline_pref) await pref.put(sortBy, this.sortBy) await pref.put(filterSpecial, JSON.stringify(this.filterSpecial)) await pref.flush() } // 加载筛选偏好 async loadFilterPreferences(): Promisevoid { const pref await preferences.getPreferences(this.context, timeline_pref) this.sortBy await pref.get(sortBy, date) as date | age this.filterSpecial JSON.parse(await pref.get(filterSpecial, false)) }九、筛选动画9.1 面板展开动画State panelHeight: number 0 State panelOpacity: number 0 showFilterOptions(): void { this.showFilterPanel !this.showFilterPanel if (this.showFilterPanel) { animateTo({ duration: 300 }, () { this.panelHeight 200 this.panelOpacity 1 }) } else { animateTo({ duration: 200 }, () { this.panelHeight 0 this.panelOpacity 0 }) } }十、最佳实践10.1 筛选功能设计原则有序列表 — 筛选功能设计的 5 个原则按钮可见筛选按钮放在列表顶部易于发现状态可感知筛选激活时按钮高亮提示用户结果可预期筛选条件改变后立即可见结果重置方便提供一键重置筛选条件持久化筛选偏好保存在本地10.2 萌宠日记筛选功能总结功能模块技术实现说明筛选按钮Text onClick右上角 ▽ 图标排序sortBy State日期/年龄排序过滤filterSpecial State只看特殊事件筛选面板条件渲染弹出/收起动画状态指示isFilterActive 计算属性按钮高亮持久化Preferences保存筛选偏好总结本文从萌宠日记的时间轴筛选与排序功能实现出发深入解析了筛选功能的完整方案筛选按钮▽ 图标点击弹出选项排序逻辑按日期/年龄排序数据过滤筛选特殊事件筛选面板胶囊按钮 Toggle 开关状态指示激活时按钮高亮结果统计显示筛选后的记录数量筛选持久化Preferences 保存偏好面板动画展开/收起过渡10.3 与时间轴列表的完整集成// 筛选与时间轴列表的完整集成 build() { Column() { // 筛选按钮 this.FilterButton() // 筛选面板条件渲染 if (this.showFilterPanel) { this.FilterPanel() } // 筛选结果统计 Text(共 ${this.sortedData.length} 条记录) .fontSize(12).fontColor(#999999) .width(100%).textAlign(TextAlign.End) .padding({ right: 16, top: 4 }) // 时间轴列表 List({ space: 0 }) { ForEach(this.sortedData, (item: TimelineItem, index: number) { ListItem() { this.TimelineItemView(item, index) } }) } .width(100%).layoutWeight(1) } .width(100%).height(100%) .backgroundColor(#FFF8F0) }10.4 筛选功能测试用例// 筛选功能测试 describe(Timeline Filter, () { it(should default to date sort, () { expect(sortBy).toBe(date) }) it(should filter special events, () { filterSpecial true expect(sortedData.every(item item.isSpecial)).toBe(true) }) it(should reset all filters, () { filterSpecial true sortBy age // 重置 sortBy date filterSpecial false expect(sortBy).toBe(date) expect(filterSpecial).toBe(false) }) })十一、筛选功能的无障碍设计11.1 无障碍适配// 筛选按钮的无障碍描述 Text(▽) .fontSize(16) .fontColor(#666666) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .backgroundColor(#F5F5F5) .borderRadius(16) .accessibilityText(筛选排序当前状态按日期排序) .onClick(() { this.showFilterOptions() })11.2 筛选面板无障碍// 筛选面板的无障碍描述 Column({ space: 12 }) { // 筛选内容 } .accessibilityText(筛选面板包含排序方式和筛选条件)十二、筛选功能的扩展12.1 多条件组合筛选interface FilterConditions { sortBy: date | age filterSpecial: boolean filterYear: string filterType: all | birthday | milestone | daily searchQuery: string } State filters: FilterConditions { sortBy: date, filterSpecial: false, filterYear: all, filterType: all, searchQuery: } // 组合筛选 get filteredAndSearchedData(): TimelineItem[] { let data [...this.timelineData] if (this.filters.filterYear ! all) { data data.filter(item item.date.startsWith(this.filters.filterYear)) } if (this.filters.filterSpecial) { data data.filter(item item.isSpecial) } if (this.filters.searchQuery) { data data.filter(item item.title.includes(this.filters.searchQuery) ) } return data }12.2 搜索功能// 搜索输入框 TextInput({ placeholder: 搜索事件... }) .width(100%).height(36) .backgroundColor(#F5F5F5).borderRadius(18) .padding({ left: 12 }) .onChange((value: string) { this.filters.searchQuery value })如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源数据排序https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/array-sort条件渲染https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-condition-variable-introductionState 装饰器https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-statePreferences 使用https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/data-persistence-by-preferences动画开发https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-animationToggle 组件https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-toggle交互反馈https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/interaction-feedback开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net

相关新闻

【Python毕业设计】个性化新闻订阅与智能采集服务平台 多源网络新闻爬虫聚合与推送系统(源码+文档+远程调试,全bao定制等)

【Python毕业设计】个性化新闻订阅与智能采集服务平台 多源网络新闻爬虫聚合与推送系统(源码+文档+远程调试,全bao定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/22 18:39:19阅读更多 →
HarmonyOS应用开发实战:萌宠日记 - 相册分类标签栏设计

HarmonyOS应用开发实战:萌宠日记 - 相册分类标签栏设计

HarmonyOS应用开发实战:萌宠日记 - 相册分类标签栏设计 前言 相册分类标签栏 是 萌宠日记 相册页的顶部导航组件,它将照片按 全部、日常、成长、旅行、其他 五个分类进行组织。用户通过点击标签切换照片分类,选中标签使用 加粗 深色文字 高…

2026/7/22 18:39:19阅读更多 →
告别低端内卷!2026国产连接器格局重塑:全赛道突围,精准匹配下游产业新需求

告别低端内卷!2026国产连接器格局重塑:全赛道突围,精准匹配下游产业新需求

曾几何时,国内连接器市场是海外品牌的主场。泰科、安费诺、莫仕垄断高端领域,国产连接器长期被扣上“低端、廉价、不稳定”的标签,只能游走在低端代工、通用配件的红海市场。但随着国内高端制造产业全面崛起,军工航天、新能源汽车…

2026/7/22 18:37:19阅读更多 →
BirdNET-Go用户界面详解:轻松掌握野生动物声音检测与数据分析

BirdNET-Go用户界面详解:轻松掌握野生动物声音检测与数据分析

BirdNET-Go用户界面详解:轻松掌握野生动物声音检测与数据分析 【免费下载链接】birdnet-go Self-hosted realtime soundscape analyser for birds, bats and other wildlife. Multi-model local AI inference, runs 24/7 on a Raspberry Pi. 项目地址: https://gi…

2026/7/22 19:39:31阅读更多 →
Spring Security退出登录功能实现:gh_mirrors/log/logback完整配置指南

Spring Security退出登录功能实现:gh_mirrors/log/logback完整配置指南

Spring Security退出登录功能实现:gh_mirrors/log/logback完整配置指南 【免费下载链接】logback 💡 SpringBootSpring Security基本配置 项目地址: https://gitcode.com/gh_mirrors/log/logback 在基于SpringBootSpring Security构建的应用中&am…

2026/7/22 19:39:31阅读更多 →
想让代码更简洁、高效、优雅?Lambda表达式与Stream流操作完全详解

想让代码更简洁、高效、优雅?Lambda表达式与Stream流操作完全详解

前言Java 8 是 Java 语言发展史上最重要的版本更新之一,其中 Lambda表达式 和 Stream流 是两大核心重磅特性。二者结合彻底改变了 Java 集合、数组的遍历、筛选、转换、聚合等操作方式,告别了繁琐的匿名内部类、循环遍历模板代码,让代码更简洁…

2026/7/22 19:39:31阅读更多 →
BuildBuddy开源社区贡献指南:从代码提交到功能开发的完整流程

BuildBuddy开源社区贡献指南:从代码提交到功能开发的完整流程

BuildBuddy开源社区贡献指南:从代码提交到功能开发的完整流程 【免费下载链接】buildbuddy BuildBuddy is an open source Bazel build event viewer, result store, remote cache, and remote build execution platform. 项目地址: https://gitcode.com/gh_mirro…

2026/7/22 19:39:31阅读更多 →
HarmonyOS应用开发实战:萌宠日记 - 地点与天气标签选择器

HarmonyOS应用开发实战:萌宠日记 - 地点与天气标签选择器

HarmonyOS应用开发实战:萌宠日记 - 地点与天气标签选择器 前言 在 萌宠日记 的日记编辑器中,地点 和 天气 是两个重要的辅助信息,它们帮助记录宠物活动时的 环境上下文。用户可以通过 标签式选择器 快速设置当前的地点(如“公园“…

2026/7/22 19:39:31阅读更多 →
特种炭黑 导电炭黑 色素炭黑

特种炭黑 导电炭黑 色素炭黑

引言:被低估的工业“黑金” 在材料科学的浩瀚星空中,有一种黑色粉末,它虽不起眼,却深刻影响着从日常橡胶制品到尖端航天科技的无数领域。它,就是特种炭黑。与普通炭黑不同,特种炭黑并非燃料不完全燃烧的简单…

2026/7/22 19:37:30阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/22 18:55:50阅读更多 →