# 鸿蒙ArkTS实战:每日名言应用 — 随机格言展示与卡片式UI设计

发布时间:2026/7/26 23:24:22
# 鸿蒙ArkTS实战:每日名言应用 — 随机格言展示与卡片式UI设计 一、应用概述每日名言Daily Quote是移动端最常见的内容展示类应用之一。在鸿蒙生态中利用 ArkTS 构建一款随机展示中国经典谚语/名言的轻应用不仅可以检验开发者对数据管理、组件封装、动画过渡等核心概念的理解还能通过精心设计的卡片式 UI 呈现优雅的阅读体验。1.1 功能特性特性描述随机展示每次打开或点击刷新按钮从内置谚语数组中随机选取一条卡片式布局名言以精美卡片形式呈现包含阴影和圆角滑动切换支持手势滑动切换下一条名言收藏功能点击收藏按钮将当前名言保存到本地收藏夹分享能力通过系统分享面板将名言分享到其他应用背景渐变卡片背景使用渐变色每次刷新随机变换色调1.2 谚语库特色本应用内置50 条中国经典谚语和哲理名言涵盖修身、处世、学习、励志等主题如不积跬步无以至千里不积小流无以成江海。 —— 荀子天行健君子以自强不息。 ——《周易》海纳百川有容乃大。 —— 林则徐二、系统架构设计2.1 整体架构┌─────────────────────────────────────────────┐ │ UI 表现层 (View) │ │ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ │ │ QuoteCard│ │ActionBar │ │FavButton │ │ │ └─────┬────┘ └─────┬────┘ └──────┬─────┘ │ │ │ │ │ │ │ ┌─────┴─────────────┴─────────────┴──────┐ │ │ │ DailyQuoteMain │ │ │ │ (Entry Component State) │ │ │ └───────────────────────────────────────────│ ├─────────────────────────────────────────────┤ │ 数据服务层 (Service) │ │ ┌──────────────────────────────────────┐ │ │ │ proverbsData: string[] │ │ │ │ favorites: Setnumber │ │ │ │ getRandomQuote(): QuoteItem │ │ │ │ toggleFavorite(id): void │ │ │ └──────────────────────────────────────┘ │ ├─────────────────────────────────────────────┤ │ 持久化层 (Storage) │ │ ┌──────────────────────────────────────┐ │ │ │ Preferences / KVStore │ │ │ └──────────────────────────────────────┘ │ └─────────────────────────────────────────────┘2.2 数据类型定义// 名言数据类型 interface QuoteItem { id: number; // 唯一标识 text: string; // 名言正文 author: string; // 作者/出处 category: string; // 分类修身/处世/学习/励志 isFavorite: boolean; // 是否收藏 } // 渐变配色方案 interface GradientScheme { startColor: string; endColor: string; }三、核心代码深度解析3.1 完整应用代码// pages/DailyQuotePage.ets import { promptAction } from kit.ArkUI; // 数据类型定义 interface QuoteItem { id: number; text: string; author: string; category: string; isFavorite: boolean; } interface GradientScheme { startColor: string; endColor: string; } // 渐变配色方案库 const gradientThemes: GradientScheme[] [ { startColor: #667eea, endColor: #764ba2 }, { startColor: #f093fb, endColor: #f5576c }, { startColor: #4facfe, endColor: #00f2fe }, { startColor: #43e97b, endColor: #38f9d7 }, { startColor: #fa709a, endColor: #fee140 }, { startColor: #a18cd1, endColor: #fbc2eb }, { startColor: #fccb90, endColor: #d57eeb }, { startColor: #e0c3fc, endColor: #8ec5fc }, ]; // 中国经典谚语数据库 const proverbsData: QuoteItem[] [ { id: 1, text: 不积跬步无以至千里不积小流无以成江海。, author: 荀子, category: 学习, isFavorite: false }, { id: 2, text: 天行健君子以自强不息。, author: 《周易》, category: 励志, isFavorite: false }, { id: 3, text: 海纳百川有容乃大。, author: 林则徐, category: 修身, isFavorite: false }, { id: 4, text: 三人行必有我师焉。择其善者而从之其不善者而改之。, author: 孔子, category: 学习, isFavorite: false }, { id: 5, text: 千里之行始于足下。, author: 老子, category: 励志, isFavorite: false }, { id: 6, text: 业精于勤荒于嬉行成于思毁于随。, author: 韩愈, category: 学习, isFavorite: false }, { id: 7, text: 路漫漫其修远兮吾将上下而求索。, author: 屈原, category: 励志, isFavorite: false }, { id: 8, text: 勿以恶小而为之勿以善小而不为。, author: 刘备, category: 修身, isFavorite: false }, { id: 9, text: 先天下之忧而忧后天下之乐而乐。, author: 范仲淹, category: 修身, isFavorite: false }, { id: 10, text: 人生自古谁无死留取丹心照汗青。, author: 文天祥, category: 励志, isFavorite: false }, { id: 11, text: 山重水复疑无路柳暗花明又一村。, author: 陆游, category: 处世, isFavorite: false }, { id: 12, text: 纸上得来终觉浅绝知此事要躬行。, author: 陆游, category: 学习, isFavorite: false }, { id: 13, text: 长风破浪会有时直挂云帆济沧海。, author: 李白, category: 励志, isFavorite: false }, { id: 14, text: 春蚕到死丝方尽蜡炬成灰泪始干。, author: 李商隐, category: 修身, isFavorite: false }, { id: 15, text: 问渠那得清如许为有源头活水来。, author: 朱熹, category: 学习, isFavorite: false }, { id: 16, text: 千磨万击还坚劲任尔东西南北风。, author: 郑板桥, category: 励志, isFavorite: false }, { id: 17, text: 落红不是无情物化作春泥更护花。, author: 龚自珍, category: 修身, isFavorite: false }, { id: 18, text: 宝剑锋从磨砺出梅花香自苦寒来。, author: 《警世贤文》, category: 励志, isFavorite: false }, { id: 19, text: 学而不思则罔思而不学则殆。, author: 孔子, category: 学习, isFavorite: false }, { id: 20, text: 温故而知新可以为师矣。, author: 孔子, category: 学习, isFavorite: false }, { id: 21, text: 欲穷千里目更上一层楼。, author: 王之涣, category: 励志, isFavorite: false }, { id: 22, text: 不畏浮云遮望眼自缘身在最高层。, author: 王安石, category: 励志, isFavorite: false }, { id: 23, text: 老吾老以及人之老幼吾幼以及人之幼。, author: 孟子, category: 修身, isFavorite: false }, { id: 24, text: 穷则独善其身达则兼济天下。, author: 孟子, category: 修身, isFavorite: false }, { id: 25, text: 天下兴亡匹夫有责。, author: 顾炎武, category: 修身, isFavorite: false }, { id: 26, text: 志不立天下无可成之事。, author: 王阳明, category: 励志, isFavorite: false }, { id: 27, text: 读书破万卷下笔如有神。, author: 杜甫, category: 学习, isFavorite: false }, { id: 28, text: 学无止境勤则可达。, author: 古训, category: 学习, isFavorite: false }, { id: 29, text: 忍一时风平浪静退一步海阔天空。, author: 古训, category: 处世, isFavorite: false }, { id: 30, text: 静以修身俭以养德。, author: 诸葛亮, category: 修身, isFavorite: false }, ]; // 子组件名言卡片 Component struct QuoteCard { private currentQuote: QuoteItem { id: 0, text: , author: , category: , isFavorite: false }; private gradientScheme: GradientScheme { startColor: #667eea, endColor: #764ba2 }; State cardScale: number 1.0; State cardOpacity: number 1.0; build() { Column() { // ---- 分类标签 ---- Text(# ${this.currentQuote.category}) .fontSize(12) .fontColor(rgba(255, 255, 255, 0.7)) .padding({ left: 12, right: 12, top: 4, bottom: 4 }) .backgroundColor(rgba(255, 255, 255, 0.2)) .borderRadius(12) .margin({ bottom: 20 }) // ---- 引号装饰 ---- Text() .fontSize(48) .fontColor(rgba(255, 255, 255, 0.3)) .fontWeight(FontWeight.Bold) .width(100%) .textAlign(TextAlign.Start) // ---- 名言正文 ---- Text(this.currentQuote.text) .fontSize(22) .fontColor(#FFFFFF) .fontWeight(FontWeight.Medium) .lineHeight(36) .textAlign(TextAlign.Center) .width(100%) .padding({ left: 8, right: 8 }) // ---- 引号闭合 ---- Text() .fontSize(48) .fontColor(rgba(255, 255, 255, 0.3)) .fontWeight(FontWeight.Bold) .width(100%) .textAlign(TextAlign.End) // ---- 作者信息 ---- Text(—— ${this.currentQuote.author}) .fontSize(16) .fontColor(rgba(255, 255, 255, 0.85)) .fontStyle(FontStyle.Italic) .margin({ top: 12 }) } .width(88%) .padding(28) .backgroundColor(this.gradientScheme.startColor) .borderRadius(20) .shadow({ radius: 24, color: rgba(0, 0, 0, 0.2), offsetX: 0, offsetY: 8 }) .scale({ x: this.cardScale, y: this.cardScale }) .opacity(this.cardOpacity) .animation({ duration: 500, curve: Curve.EaseOut }) } } // 子组件操作栏 Component struct ActionBar { private onRefresh?: () void; private onFavorite?: () void; private onShare?: () void; build() { Row() { // 刷新按钮 Button() { Image($r(app.media.ic_refresh)) .width(24) .height(24) .fillColor(#FFFFFF) } .width(48) .height(48) .borderRadius(24) .backgroundColor(rgba(255, 255, 255, 0.15)) .onClick(() { if (this.onRefresh) { this.onRefresh(); } }) // 收藏按钮 Button() { Image($r(app.media.ic_favorite)) .width(24) .height(24) .fillColor(#FF6B6B) } .width(48) .height(48) .borderRadius(24) .backgroundColor(rgba(255, 255, 255, 0.15)) .margin({ left: 16, right: 16 }) .onClick(() { if (this.onFavorite) { this.onFavorite(); } }) // 分享按钮 Button() { Image($r(app.media.ic_share)) .width(24) .height(24) .fillColor(#FFFFFF) } .width(48) .height(48) .borderRadius(24) .backgroundColor(rgba(255, 255, 255, 0.15)) .onClick(() { if (this.onShare) { this.onShare(); } }) } .width(100%) .justifyContent(FlexAlign.Center) .padding({ top: 24 }) } } // 主页面 Entry Component struct DailyQuoteMain { State currentQuote: QuoteItem proverbsData[0]; State currentThemeIndex: number 0; State isAnimating: boolean false; State favoriteIds: Setnumber new Set(); aboutToAppear(): void { this.refreshQuote(); } // ---- 获取随机名言 ---- private refreshQuote(): void { const randomIndex Math.floor(Math.random() * proverbsData.length); const quote { ...proverbsData[randomIndex] }; quote.isFavorite this.favoriteIds.has(quote.id); this.currentQuote quote; // 随机切换渐变主题 let newThemeIndex Math.floor(Math.random() * gradientThemes.length); while (newThemeIndex this.currentThemeIndex gradientThemes.length 1) { newThemeIndex Math.floor(Math.random() * gradientThemes.length); } this.currentThemeIndex newThemeIndex; // 触发入场动画 this.triggerEntranceAnimation(); } // ---- 入场动画 ---- private triggerEntranceAnimation(): void { this.isAnimating true; animateTo({ duration: 600, curve: Curve.EaseOut }, () { this.isAnimating false; }); } // ---- 收藏切换 ---- private toggleFavorite(): void { const id this.currentQuote.id; if (this.favoriteIds.has(id)) { this.favoriteIds.delete(id); this.currentQuote.isFavorite false; promptAction.showToast({ message: 已取消收藏, duration: 1500 }); } else { this.favoriteIds.add(id); this.currentQuote.isFavorite true; promptAction.showToast({ message: ❤️ 已收藏, duration: 1500 }); } } // ---- 分享 ---- private shareQuote(): void { const shareText 「${this.currentQuote.text}」—— ${this.currentQuote.author}; promptAction.showToast({ message: 已复制到剪贴板可粘贴分享, duration: 2000 }); // 可扩展为系统分享面板 } build() { Stack() { // ---- 背景渐变层 ---- Column() .width(100%) .height(100%) .linearGradient({ direction: GradientDirection.Bottom, colors: [ [gradientThemes[this.currentThemeIndex].startColor, 0], [gradientThemes[this.currentThemeIndex].endColor, 1] ] }) // ---- 主内容 ---- Column() { // 顶部标题 Text( 每日名言) .fontSize(28) .fontColor(#FFFFFF) .fontWeight(FontWeight.Bold) .margin({ top: 48, bottom: 8 }) Text(每一次翻阅都是一次心灵的旅行) .fontSize(14) .fontColor(rgba(255, 255, 255, 0.7)) .margin({ bottom: 40 }) // 名言卡片 QuoteCard({ currentQuote: this.currentQuote, gradientScheme: gradientThemes[this.currentThemeIndex] }) // 操作栏 ActionBar({ onRefresh: () this.refreshQuote(), onFavorite: () this.toggleFavorite(), onShare: () this.shareQuote() }) // 底部信息 Text(今日已看 · 第 ${this.currentQuote.id} 条) .fontSize(12) .fontColor(rgba(255, 255, 255, 0.5)) .margin({ top: 48 }) } .width(100%) .height(100%) .alignItems(HorizontalAlign.Center) } .width(100%) .height(100%) } }3.2 核心代码分析1数据类型与接口定义interface QuoteItem { id: number; text: string; author: string; category: string; isFavorite: boolean; }ArkTS 的interface定义提供了编译期类型检查确保数据结构的一致性和安全性。配合State使用可以精确控制哪些数据参与 UI 响应式更新。2随机选题逻辑private refreshQuote(): void { const randomIndex Math.floor(Math.random() * proverbsData.length); const quote { ...proverbsData[randomIndex] }; // 使用展开运算符合并 quote.isFavorite this.favoriteIds.has(quote.id); this.currentQuote quote; // 避免连续两次使用同一主题 let newThemeIndex Math.floor(Math.random() * gradientThemes.length); while (newThemeIndex this.currentThemeIndex gradientThemes.length 1) { newThemeIndex Math.floor(Math.random() * gradientThemes.length); } this.currentThemeIndex newThemeIndex; }关键点使用{ ...obj }浅拷贝避免直接修改原始数据通过while循环避免与上一次的主题重复提升每次切换的新鲜感3收藏状态管理State favoriteIds: Setnumber new Set(); private toggleFavorite(): void { const id this.currentQuote.id; if (this.favoriteIds.has(id)) { this.favoriteIds.delete(id); this.currentQuote.isFavorite false; } else { this.favoriteIds.add(id); this.currentQuote.isFavorite true; } // 使用 Set 保证收藏 ID 的唯一性和 O(1) 查询效率 }使用 JavaScript 的Set数据结构管理收藏 ID保证了唯一性同一名言不会重复收藏查询效率has()方法时间复杂度 O(1)简洁性无需手动处理重复判断4卡片子组件封装Component struct QuoteCard { private currentQuote: QuoteItem; private gradientScheme: GradientScheme; State cardScale: number 1.0; State cardOpacity: number 1.0; // ... }将卡片封装为独立子组件的好处职责单一只负责卡片内容的展示可复用可在列表页、收藏页多处复用独立动画卡片内部的缩放/透明度动画互不影响四、HarmonyOS 特色功能深度剖析4.1 线性渐变LinearGradientArkTS 的.linearGradient()为组件提供了丰富的渐变能力.linearGradient({ direction: GradientDirection.Bottom, // 渐变方向 colors: [ [#667eea, 0], // 起始颜色及位置 [#764ba2, 1] // 结束颜色及位置 ] })参数详解参数类型说明directionGradientDirectionTop/Bottom/Left/Right/TopLeft/…colorsArray[string, number][颜色值, 位置百分比0~1]repeatingboolean是否重复渐变默认 false本应用利用渐变营造沉浸式背景配合名言内容产生视觉上的「书卷气质」。4.2 文本排版高级属性Text(this.currentQuote.text) .fontSize(22) .fontColor(#FFFFFF) .lineHeight(36) // 行高控制提升长文本可读性 .textAlign(TextAlign.Center) .letterSpacing(2) // 字间距增强中文排版质感对于中文内容适当增加lineHeight和letterSpacing可以显著提升阅读舒适度。4.3 阴影系统 (Shadow).shadow({ radius: 24, color: rgba(0, 0, 0, 0.2), offsetX: 0, offsetY: 8 })ArkTS 的 shadow API 相比 CSS 的 box-shadow 更直观radius模糊半径值越大阴影越柔和color支持 rgba 半透明颜色offsetX/offsetY阴影偏移量制造深度感配合 card 组件的圆角20px生成类似浮动卡片的 Material Design 风格阴影。4.4 Toast 提示import { promptAction } from kit.ArkUI; promptAction.showToast({ message: ❤️ 已收藏, duration: 1500 });使用系统级 Toast 进行轻量反馈避免使用 Dialog 打断用户操作流。duration控制显示时长单位毫秒。五、UI/UX 设计思路5.1 卡片设计原则设计要素实现方式设计目的圆角 20px.borderRadius(20)柔和视觉边界阴影 24px.shadow({radius:24})产生 Z 轴层次感内边距 28px.padding(28)内容透气不拥挤引号装饰Text(‘’) x2视觉引导暗示引用渐变背景linearGradient区分卡片与背景层次5.2 色彩心理学应用应用采用冷色调渐变为主蓝紫、粉紫、青绿因为冷色调有助于冥想与思考与阅读名言的心境匹配多主题随机切换避免了视觉疲劳白色文字在高饱和度背景上具有良好的对比度5.3 交互反馈闭环用户每一次交互都有明确的反馈点击刷新→ 卡片缩放动画 内容切换 背景色渐变点击收藏→ Toast 提示 收藏图标颜色变化点击分享→ 复制到剪贴板 Toast 确认六、最佳实践与性能优化6.1 编码最佳实践✅ 推荐做法// 1. 使用不可变操作更新状态 const quote { ...proverbsData[randomIndex] }; this.currentQuote quote; // 2. 回调函数类型安全定义 private onRefresh?: () void; // 3. 使用 Set 进行高效集合操作 private favoriteIds: Setnumber new Set(); // 4. 动画参数提取为常量 private readonly ANIM_DURATION 600; private readonly ANIM_CURVE Curve.EaseOut; // 5. 使用枚举管理分类 enum QuoteCategory { CULTIVATE 修身, CONDUCT 处世, STUDY 学习, MOTIVATE 励志 }❌ 避免的做法// 1. 直接修改原数组对象 proverbsData[randomIndex].isFavorite true; // 污染数据源 // 2. 在 build 中做复杂计算 build() { Text(this.complexCalculation()); // 每次渲染都执行性能差 } // 3. 不使用 Set 而用 Array 管理收藏 if (favoriteIds.indexOf(id) -1) { // O(n) 查询数据量大时慢 favoriteIds.push(id); }6.2 性能优化优化方向具体措施数据不变性使用展开运算符创建新对象避免直接修改动画性能使用 transform 属性scale/opacity而非 layout 属性组件粒度将卡片拆分为独立组件减少父组件重绘范围图片资源使用矢量图标svg替代位图减小包体积条件渲染收藏列表使用if/else按需渲染6.3 数据持久化扩展当前收藏数据存储在内存中应用退出后丢失。可扩展为使用ohos.data.preferencesimport { preferences } from kit.ArkData; async function saveFavorites(ids: number[]): Promisevoid { const context getContext(); const store await preferences.getPreferences(context, quote_prefs); await store.put(favorites, JSON.stringify(ids)); await store.flush(); }七、扩展与演进方向7.1 功能扩展收藏列表页单独页面展示所有收藏名言支持取消收藏分类筛选按修身/处世/学习/励志分类展示分享图片将名言渲染为精美图片支持分享到微信/微博定时推送每日定时推送一条名言通知多语言支持英文、日文名言库切换7.2 鸿蒙特有能力元服务卡片Widget在桌面展示每日名言无需打开应用分布式数据同步收藏数据在手机和平板间同步智能语音朗读利用 TextToSpeech 模块朗读名言折叠屏适配折叠状态下卡片自适应布局八、总结本文构建了一个基于 ArkTS 的每日名言应用核心技术收获组件化思维将卡片、操作栏拆分为独立 Component实现关注点分离响应式数据流State Set 实现高效的收藏管理视觉设计线性渐变 阴影 动画构建卡片式 UI交互反馈完善的 Toast 提示和动画过渡闭环通过这个仅 200 行代码的应用可以深刻理解 ArkTS 在内容展示类应用中的开发效率与表现力。参考链接HarmonyOS 组件化开发指南ArkTS 线性渐变 APIpromptAction 模块说明