鸿蒙 ArkTS 实战:Basketball Scorekeeper 从篮球记分牌到兴趣活动工具完整解析
前言
Basketball Scorekeeper 是一个围绕比赛记分场景设计的鸿蒙 ArkTS 单页应用。
它的价值不在于复杂功能堆叠,而在于把 在半场或全场比赛中显示双方队名与比分,并记录球员数据和下一场安排 这件事压缩成一个可以快速打开、快速记录、快速反馈的移动端页面。
本文会基于项目真实的Index.ets代码,拆解它的状态模型、布局结构、交互逻辑、视觉层级和可扩展方向。
图示说明:配图用于表达鸿蒙 ArkTS 应用从状态、组件到交互反馈的组织方式,重点帮助理解页面结构。
阅读时可以结合 HarmonyOS 应用开发文档、ArkTS 语言基础、ArkUI 声明式开发范式、组件参考 等资料,快速定位 ArkTS、ArkUI 与组件开发相关能力。
小型兴趣活动工具最重要的是把一次操作闭环做完整:用户输入什么、点击什么、页面反馈什么,都要一眼能看懂。
一、应用定位与场景价值
1.1 解决的真实问题
篮球记分牌 解决的是一个非常具体的场景:在半场或全场比赛中显示双方队名与比分,并记录球员数据和下一场安排。
这类应用通常不需要复杂的账号系统,也不需要一开始就接入云端。
它首先要做到的是让用户在一个页面里完成核心记录。
1.2 适合的用户群体
本文面向 想实现运动记分、顶部大屏比分和即时按钮反馈的 ArkTS 开发者。
从代码学习角度看,这个项目适合观察三件事。
- 如何用
@State保存页面数据。 - 如何用 ArkUI 组件表达业务结构。
- 如何让按钮事件形成即时反馈。
1.3 为什么用鸿蒙 ArkTS 实现
ArkTS 的声明式 UI 写法适合这类工具。
状态在组件中声明,组件直接引用状态,事件函数修改状态,界面随之更新。
这种写法能把业务逻辑和页面反馈放在一起阅读,对学习项目尤其友好。
二、工程入口与页面骨架
2.1 页面文件位置
项目核心页面位于Index.ets。
entry/ src/ main/ ets/ pages/ Index.ets入口页面承担了三个职责:声明状态、处理交互、构建 UI。
2.2 入口组件声明
项目使用@Entry和@Component声明页面组件。
@Entry@Componentstruct Index{build(){// 页面结构}}这种结构是鸿蒙 ArkUI 页面开发的基础模式。
2.3 页面骨架特征
Basketball Scorekeeper 的页面骨架可以概括为:顶部深色比分区占据页面 38% 高度,左右两列显示队名与大号分数,内容区记录球员和赛程。
这个骨架很适合移动端,因为主信息直接进入首屏,辅助信息通过输入区和结果区逐步展开。
三、状态模型拆解
3.1 状态字段总览
| 状态字段 | 初始值 | 页面职责 |
|---|---|---|
team | Blue Team | 主队名称 |
opponent | Red Team | 对手名称 |
scoreA | 42 | 主队比分 |
scoreB | 39 | 对手比分 |
player | Chen 12pts 5reb | 球员数据 |
schedule | Next game Saturday | 赛程提醒 |
这些状态字段覆盖了 篮球记分牌 的主要业务信息。
3.2 状态字段的语义边界
状态字段不是随意命名的变量,而是页面语义的一部分。
例如team表达主记录,schedule表达反馈状态。
这种命名方式让读者不需要跳转多个文件,也能理解页面正在做什么。
3.3 核心源码片段
@Stateteam:string='Blue Team';@Stateopponent:string='Red Team';@StatescoreA:number=42;@StatescoreB:number=39;@Stateplayer:string='Chen 12pts 5reb';@Stateschedule:string='Next game Saturday';这段代码展示了页面数据如何被声明和更新。
对于小型工具来说,把状态集中放在入口组件中是可读性很高的做法。
四、交互逻辑设计
4.1 交互点总览
| 交互点 | 源码行为 | 页面反馈 |
|---|---|---|
+2 Blue | 主队比分增加 2 分 | 用户能立即看到状态变化 |
+2 Red | 对手比分增加 2 分 | 用户能立即看到状态变化 |
Player stats 输入 | 记录球员得分和篮板信息 | 用户能立即看到状态变化 |
交互点的共同特点是动作短、反馈快。
用户点击按钮后,页面不会跳转到复杂流程,而是直接更新当前页面可见的文字或数字。
4.2 输入框的同步机制
输入框通过onChange把用户输入写回状态。
TextInput({text:this.team,placeholder:'主队名称'}).onChange((v:string)=>this.team=v)这种方式适合字段数量有限的页面。
当字段变多时,可以抽出通用输入组件,减少重复代码。
4.3 结果反馈的表达方式
结果反馈应该能复述用户刚刚完成的动作。
this.schedule='Updated by '+this.team;清晰反馈能让用户确认操作已经生效。
五、布局结构与视觉层级
5.1 关键 UI 片段
Row(){Column(){Text(this.team).fontSize(18).fontColor('#DBEAFE')Text(this.scoreA.toString()).fontSize(64).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')}.layoutWeight(1).alignItems(HorizontalAlign.Center)Column(){Text(this.opponent).fontSize(18).fontColor('#FEE2E2')Text(this.scoreB.toString()).fontSize(64).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')}.layoutWeight(1).alignItems(HorizontalAlign.Center)}.height('38%').width('100%').backgroundColor('#111827')这段代码是项目最有代表性的布局部分。
它通过Row、Column、Grid、Scroll或条件背景色,把关键状态放到更容易被注意的位置。
5.2 页面主次关系
页面主次关系可以分为三层。
- 第一层:标题、比分、人数、地点或主卡片。
- 第二层:输入字段和操作按钮。
- 第三层:状态说明、提醒和补充记录。
这种分层让用户可以先看结果,再决定是否编辑细节。
5.3 滚动区域的必要性
很多活动工具都包含多个字段。
使用Scroll可以保证小屏设备也能完整操作。
Scroll(){Column({space:16}){// 内容区}.padding(20).width('100%')}滚动容器让页面保持稳定,也避免按钮被屏幕高度挤出。
六、数据计算与边界处理
6.1 字符串状态处理
多数活动工具会把多个输入字段组合成一段反馈。
constsummary=this.team+' / '+this.schedule;这种拼接不是简单展示,而是把零散输入变成可阅读的活动记录。
6.2 数字状态处理
项目中涉及人数、比分、照片、费用、点数或签到数等数字。
this.count++;constsplit=Math.round(Number(this.cost)/this.members);数字状态要特别关注两个点:类型转换和边界值。
6.3 条件展示处理
当页面需要根据状态改变样式时,可以使用条件表达式。
Text(this.enabled?'Ready':'Pending').backgroundColor(this.enabled?'#DCFCE7':'#FEE2E2')条件样式能让用户在不读长文本的情况下理解状态。
七、活动工具的体验设计
7.1 首屏信息要明确
Basketball Scorekeeper 的首屏把关键状态放在最显眼的位置。
对于 比赛记分 场景,用户通常是在活动现场或活动前快速查看信息。
因此页面不应该隐藏最重要的内容。
7.2 输入成本要低
项目采用短输入框和短按钮文案,降低了记录成本。
| 输入类型 | 页面用途 | 体验特点 |
|---|---|---|
| 文本输入 | 记录名称、地点、说明 | 灵活 |
| 数字输入 | 记录费用、人数、比分 | 直观 |
| 按钮点击 | 加入、签到、投票、提交 | 快速 |
7.3 反馈要贴近场景
不同场景的反馈文案不应该完全一样。
篮球记分牌 的反馈围绕 在半场或全场比赛中显示双方队名与比分,并记录球员数据和下一场安排 展开,因此用户读到结果时能知道它对应哪一次活动。
八、组件能力映射
8.1 ArkUI 组件使用
| 组件 | 在项目中的作用 | 适合原因 |
|---|---|---|
Text | 显示标题、状态和结果 | 简洁直接 |
TextInput | 编辑活动信息 | 输入成本低 |
Button | 触发状态变化 | 操作明确 |
Row | 横向展示多个指标 | 适合并列信息 |
Column | 纵向组织内容 | 阅读顺序自然 |
8.2 布局参数的作用
页面中常见的.padding(20)、.borderRadius(8)、.layoutWeight(1)都是为了保证移动端可读性。
Text('Card').padding(16).backgroundColor('#111827').borderRadius(8)这些参数让卡片有足够留白,也让并列内容更加稳定。
8.3 背景色与强调色
当前页面背景色是#F8FAFC,强调色是#111827。
背景色负责降低阅读压力,强调色负责突出当前最重要的信息。
九、可维护性分析
9.1 当前实现的优点
Basketball Scorekeeper 当前实现有几个优点。
- 状态字段数量适中。
- 交互函数短小。
- 页面结构集中。
- 业务语义明确。
- 适合继续迭代。
这些特点让项目很适合作为鸿蒙 ArkTS 实战文章案例。
9.2 可能增长的复杂度
当活动记录变多后,复杂度会从单条状态转向列表数据。
例如报名名单、历史比分、材料采购明细、照片集合和路线记录,都可能需要数组结构。
9.3 数据对象示例
interfaceActivityRecord{id:string;title:string;detail:string;count:number;updatedAt:number;}把记录抽象成对象后,页面就可以从单次工具升级为历史记录工具。
十、列表化扩展
10.1 数组状态
@Staterecords:ActivityRecord[]=[];数组状态适合保存多条活动记录。
10.2 渲染列表
ForEach(this.records,(item:ActivityRecord)=>{Text(item.title).fontSize(18).fontWeight(FontWeight.Medium)})列表化之后,用户可以回看历史活动,而不是只看当前一次记录。
10.3 新增记录
this.records=[...this.records,{id:Date.now().toString(),title:this.team,detail:this.schedule,count:1,updatedAt:Date.now()}];这种不可变更新方式更容易触发页面刷新。
十一、本地持久化思路
11.1 为什么需要持久化
活动类工具一旦进入真实使用,就需要保存历史数据。
如果不持久化,用户每次重新打开页面都会失去上一次记录。
11.2 持久化数据结构
interfacePersistedActivityState{currentTitle:string;currentDetail:string;records:ActivityRecord[];version:number;}加入version可以为后续字段升级预留空间。
11.3 读取后的状态恢复
functionrestoreTitle(saved:PersistedActivityState):string{returnsaved.currentTitle||'';}恢复状态时要考虑旧数据缺字段的情况。
十二、调试路径
12.1 先看状态是否变化
Button('Debug').onClick(()=>{console.info('current value: '+this.team);})如果日志变化而页面不变,通常是 UI 没有引用正确字段。
12.2 再看数字计算
涉及费用、人均、比分和人数时,要检查输入为空或无法转换数字的情况。
constraw=Number(this.cost);constsafeCost=Number.isNaN(raw)?0:raw;这能避免用户输入异常时出现不可读结果。
12.3 最后看小屏适配
小屏设备上要重点观察输入框、按钮和卡片是否拥挤。
如果内容多,优先保证Scroll可用。
十三、常见问题处理
13.1 输入为空
输入为空时,可以继续显示 placeholder,并在结果区保留最近一次有效反馈。
13.2 数字不合法
数字输入要考虑空字符串。
functiontoSafeNumber(value:string):number{constn=Number(value);returnNumber.isNaN(n)?0:n;}这样能避免费用分摊或统计显示出现异常。
13.3 文本过长
文本过长时,可以用滚动容器承接,而不是让卡片无限撑高。
| 维度 | 当前实现 | 扩展方向 |
|---|---|---|
| 数据来源 | 页面内@State | 可接入本地持久化 |
| 交互方式 | 输入框加按钮 | 可加入筛选、搜索和批量操作 |
| 视觉重点 | #111827强调主信息 | 可形成主题色配置 |
| 使用场景 | 在半场或全场比赛中显示双方队名与比分,并记录球员数据和下一场安排 | 可扩展成多记录管理 |
十四、工程化拆分
14.1 抽离卡片组件
@BuilderfunctionMetricCard(label:string,value:string,color:string){Column({space:6}){Text(label).fontSize(14).fontColor('#6B7280')Text(value).fontSize(20).fontWeight(FontWeight.Bold)}.padding(16).backgroundColor(color).borderRadius(8)}这个组件可以复用在人数、比分、费用、签到和照片等指标上。
14.2 抽离业务函数
exportfunctionbuildActivityStatus(title:string,action:string):string{returntitle+' - '+action;}业务函数独立后,页面代码会更专注于 UI。
14.3 抽离主题配置
constTheme={pageBg:'#F8FAFC',accent:'#111827',radius:8,padding:20};统一主题配置可以减少重复修改。
十五、发布级技术亮点
15.1 单页闭环完整
篮球记分牌 已经完成从输入到反馈的闭环。
用户可以在一个页面里完成主要操作,而不需要跳转。
15.2 业务语义清楚
字段名、按钮名和结果文本都围绕 比赛记分 展开。
这让代码不仅能运行,也能被读懂。
15.3 易于继续扩展
当前实现可以自然扩展到历史记录、数据持久化、统计图和分享能力。
对活动类应用来说,先把一次活动记录做顺,再扩展到多次活动管理,是更稳的产品演进路线。
十六、总结
Basketball Scorekeeper 展示了一个鸿蒙 ArkTS 小应用如何把 比赛记分 场景落到页面代码里。
它用@State保存核心数据,用输入框完成编辑,用按钮触发状态变化,再通过卡片、数字和结果文本反馈给用户。
从学习价值看,这个项目覆盖了状态管理、布局组织、输入同步、按钮事件和视觉层级,是一个适合拆解和复用的单页工具案例。
从产品价值看,篮球记分牌 把 在半场或全场比赛中显示双方队名与比分,并记录球员数据和下一场安排 这件事变得更轻、更快、更容易执行。
相关资源:
- HarmonyOS 应用开发文档
- ArkTS 语言基础
- ArkUI 声明式开发范式
- 组件参考
- 状态管理
- 应用工程结构
- 性能调优
- DevEco Studio
onsumer/cn/doc/harmonyos-guides/arkts-ui-development) - 组件参考
- 状态管理
- 应用工程结构
- 性能调优