鸿蒙原生应用实战(三):设置与统计页面开发 — 数据驱动的功能模块
鸿蒙原生应用实战三设置与统计页面开发 — 数据驱动的功能模块前言前两篇我们完成了首页和游戏核心页面。本篇将聚焦于两个功能性页面——设置SettingsPage和统计StatsPage它们共同构成了游戏的配置与数据展示层。通过本篇你将学到Toggle 开关组件与表单布局Scroll 滚容器在内容长页面中的应用数据统计的可视化展示技巧卡片式 UI 设计模式资源引用与多态样式的组合运用一、设置页面 — SettingsPage设置页面是用户自定义游戏体验的地方。我们设计了三组设置项游戏设置、关于信息、数据重置。1.1 页面结构规划SettingsPage ├── 标题栏返回按钮 标题 ├── Scroll 滚容器 │ ├── 游戏设置卡片 │ │ ├── 音效开关 │ │ ├── 高亮相同数字开关 │ │ └── 自动检查开关 │ ├── 关于卡片 │ │ ├── 版本号 │ │ └── 开发信息 │ └── 重置按钮1.2 完整代码实现importrouterfromohos.router;EntryComponentstruct SettingsPage{StatesoundEnabled:booleantrue;// 音效StatehighlightEnabled:booleantrue;// 高亮相同数字StateautoCheckEnabled:booleanfalse;// 自动检查build(){Column(){// 标题栏 Row(){Button(←).fontSize(22).fontColor($r(app.color.text_primary)).backgroundColor(Color.Transparent).onClick((){router.back();})Text($r(app.string.title_settings)).fontSize($r(app.float.page_title_font_size)).fontWeight(FontWeight.Bold).fontColor($r(app.color.text_primary)).margin({left:12})}.width(100%).padding($r(app.float.padding_medium))Scroll(){Column(){// 游戏设置卡片 this.settingCard()// 关于卡片 this.aboutCard()// 重置按钮 Button(重置所有数据).width(100%).height(48).backgroundColor(Color.White).borderRadius($r(app.float.btn_corner_radius)).fontColor($r(app.color.status_exception)).fontSize($r(app.float.body_font_size)).border({width:1,color:$r(app.color.status_exception)}).margin({top:32})}.width(90%)}.width(100%).layoutWeight(1)}.width(100%).height(100%).backgroundColor($r(app.color.background))}}1.3 Toggle 开关组件详解ArkTS 提供了Toggle组件来实现开关效果语法如下Toggle({type:ToggleType.Switch,isOn:this.soundEnabled}).onChange((value:boolean){this.soundEnabledvalue;})参数说明参数说明type开关类型ToggleType.Switch滑动开关或ToggleType.Checkbox复选框isOn初始状态true开或false关onChange状态变化回调接收当前值每个设置项采用标签 开关的左右布局Row(){Text($r(app.string.sound_effect))// 左侧标签.fontSize($r(app.float.body_font_size)).fontColor($r(app.color.text_primary))Blank()// 中间弹性空间Toggle({type:ToggleType.Switch,isOn:this.soundEnabled})// 右侧开关.onChange((value:boolean){this.soundEnabledvalue;})}.width(100%).height(52).padding({left:16,right:16})Blank()在这里发挥了关键作用——它会尽可能占据中间空间把文字推到左边开关推到右边实现两端对齐的效果。1.4 Divider 分割线设置项之间使用Divider分隔Divider().width(100%)默认Divider是横跨全屏的但在卡片内我们想让它在左右留一些边距。可以在外层控制宽度或者给Divider添加margin。1.5 卡片式设计所有设置分组都被包裹在圆角白色卡片中Column(){Text(游戏设置).fontSize($r(app.float.body_font_size)).fontWeight(FontWeight.Medium).fontColor($r(app.color.text_primary)).margin({bottom:8})// ... 设置项 ...}.width(100%).padding({top:8}).backgroundColor($r(app.color.card_bg)).borderRadius($r(app.float.card_corner_radius))这种卡片设计在鸿蒙应用中非常普遍好处是视觉上自然分组提升可读性统一的圆角半径12vp和白色背景形成设计规范多张卡片之间用margin({ top: 16 })保持间距1.6 关于信息与重置按钮关于卡片采用标签-值的列表形式展示只读信息Row(){Text(版本).fontSize($r(app.float.body_font_size)).fontColor($r(app.color.text_primary))Blank()Text(v1.0.0).fontSize($r(app.float.small_font_size)).fontColor($r(app.color.text_hint))}.width(100%).height(52).padding({left:16,right:16})重置按钮采用描边红色样式警示用户这是一个危险操作Button(重置所有数据).backgroundColor(Color.White).fontColor($r(app.color.status_exception))// 红色文字.border({width:1,color:$r(app.color.status_exception)})// 红色边框二、Scroll 滚容器设置内容和统计内容都比较长需要使用Scroll组件实现滚Scroll(){Column(){// 所有内容放在 Column 中}.width(90%)}.width(100%).layoutWeight(1)关键设计点外层 ColumnScroll的外层占满剩余空间layoutWeight(1)Scroll占据可用高度内容溢出时显示滚条内层 Column内容容器宽度为90%左右留边距高度自适应layoutWeight(1)的含义是占据剩余空间中的 1 份权重为 1。因为外层Column中标题栏占固定高度剩下的空间全部分配给Scroll。三、统计页面 — StatsPage统计页面展示玩家的游戏数据包括总览、难度分布和最佳成绩。3.1 页面布局StatsPage ├── 标题栏 └── Scroll ├── 游戏总览卡片 │ ├── 完成局数 │ ├── 平均用时 │ └── 完成率 ├── 难度统计卡片 │ ├── 简单局数 平均用时 进度条 │ ├── 中等 │ └── 困难 └── 最佳成绩卡片 ├── 简单最快 ├── 中等最快 └── 困难最快3.2 总览统计使用三列等比分栏展示Row(){// 完成局数Column(){Text(12).fontSize(32).fontWeight(FontWeight.Bold).fontColor($r(app.color.primary))Text($r(app.string.games_completed)).fontSize($r(app.float.small_font_size)).fontColor($r(app.color.text_hint)).margin({top:4})}.layoutWeight(1).alignItems(HorizontalAlign.Center)// 平均用时Column(){Text(15:32).fontSize(24).fontWeight(FontWeight.Bold).fontColor($r(app.color.primary))Text($r(app.string.avg_time)).fontSize($r(app.float.small_font_size)).fontColor($r(app.color.text_hint)).margin({top:4})}.layoutWeight(1).alignItems(HorizontalAlign.Center)// 完成率Column(){Text(85%).fontSize(24).fontWeight(FontWeight.Bold).fontColor($r(app.color.status_delivered))// 绿色Text(完成率).fontSize($r(app.float.small_font_size)).fontColor($r(app.color.text_hint)).margin({top:4})}.layoutWeight(1).alignItems(HorizontalAlign.Center)}三个设计细节layoutWeight(1)让三列均分宽度数字字体大小不同32/24主次分明完成率用绿色status_delivered表示正面数据3.3 进度条模拟目前项目使用 ASCII 字符█来模拟进度条后续可改为自定义进度组件// 简单满进度Row(){Text(██████████).fontSize(14).fontColor($r(app.color.status_delivered))// 绿色}// 中等80% 进度Row(){Text(████████).fontSize(14).fontColor($r(app.color.rating_star))// 黄色}// 困难60% 进度Row(){Text(██████).fontSize(14).fontColor($r(app.color.status_exception))// 红色}这是一个临时方案。实际应用中可以用Columnoverlay组合来模拟真正的进度条就像我们在成就系统中做的Row(){Column().width(100%).height(8).backgroundColor(#FFF0F0F0).borderRadius(4).overlay((){Column().width(60%)// 进度百分比.height(8).backgroundColor($r(app.color.primary)).borderRadius(4)})}3.4 最佳成绩列表Row(){Text( 简单).fontSize($r(app.float.body_font_size)).fontColor($r(app.color.text_primary))Blank()Text(03:25).fontSize(18).fontWeight(FontWeight.Bold).fontColor($r(app.color.rating_star))// 金色}每个难度一行用Blank()实现左右对齐时间数字用金色表示荣誉感。四、通用设计模式总结通过 SettingsPage 和 StatsPage 的开发我们可以总结出几个鸿蒙 ArkTS 的通用设计模式4.1 页面标题栏模式Row(){Button(←).fontSize(22).fontColor($r(app.color.text_primary)).backgroundColor(Color.Transparent).onClick((){router.back();})Text(页面标题).fontSize($r(app.float.page_title_font_size)).fontWeight(FontWeight.Bold).fontColor($r(app.color.text_primary)).margin({left:12})Blank()// 如果右侧也需要元素可以在 Blank 之后添加}.width(100%).padding($r(app.float.padding_medium))4.2 卡片式内容分组Column(){Text(分组标题).fontSize($r(app.float.body_font_size)).fontWeight(FontWeight.Medium)// ...// 内容项...}.width(100%).padding(16).backgroundColor($r(app.color.card_bg)).borderRadius($r(app.float.card_corner_radius))4.3 标签-值列表项Row(){Text(标签).fontColor($r(app.color.text_primary))Blank()Text(值).fontColor($r(app.color.text_hint))}.width(100%).height(52).padding({left:16,right:16})4.4 危险操作按钮Button(危险操作).backgroundColor(Color.White).fontColor($r(app.color.status_exception)).border({width:1,color:$r(app.color.status_exception)})五、资源文件的复用在整个项目中颜色/字号/字符串都通过$r引用资源文件保证了一致性资源引用实际值使用位置$r(app.color.primary)#FF5C6BC0靛蓝按钮、标题、数值$r(app.color.background)#FFF5F5F5浅灰页面背景$r(app.color.card_bg)#FFFFFF白卡片背景$r(app.color.text_primary)#FF333333主文字$r(app.color.text_hint)#FF999999辅助文字$r(app.color.status_delivered)#FF4CAF50绿正面数据$r(app.color.status_exception)#FFF44336红警告/错误数据$r(app.float.page_title_font_size)22fp页面标题$r(app.float.body_font_size)16fp正文$r(app.float.small_font_size)13fp小字注释$r(app.float.card_corner_radius)12vp卡片圆角这种集中管理的方式在需要调整视觉风格时只需修改资源文件无需遍历所有页面。六、小结与预告本篇我们完成了✅ SettingsPage 设置页面Toggle 开关 卡片布局 Scroll 滚✅ StatsPage 统计页面总览数据 难度分布 最佳成绩✅ 通用的页面设计模式总结✅ 资源文件的规范复用值得一提的是这些页面的数据目前都是静态写死的。在实际应用中应该通过AppStorage或PersistentStorage实现数据持久化——这会在后续篇章中介绍。下一篇我们将开发成就系统和排行榜两个非常有趣的页面12 个精心设计的成就带进度追踪排行榜的分难度排名展示分类筛选与列表渲染优化敬请期待