HarmonyOS应用开发实战:猫猫大作战-Badge 的基本用法、位置与样式定制、与 Stack 手搓的取舍
前言游戏里经常见到这种提示——「最高分 NEW 标」「未读消息红点」「活动倒计时角标」。这些挂在组件右上角的小标记HarmonyOS 提供了Badge组件一行搞定不用自己用Stack叠红点。本篇以「猫猫大作战」主菜单最高分徽章加 NEW 标为锚点把 Badge 的基本用法、位置与样式定制、与 Stack 手搓的取舍三大要点讲透。提示本系列不讲 ArkTS 基础语法与环境搭建假设你已跟完第 1–25 篇。本篇是布局进阶的第六篇。一、场景拆解最高分 NEW 角标回顾「猫猫大作战」主菜单最高分行第 8 篇// 来源entry/src/main/ets/pages/Index.ets MainMenuView() if (this.highScore 0) { Row() { Text( 最高分: ).fontSize(16).fontColor(#F1C40F) Text(this.highScore.toString()).fontSize(20).fontWeight(FontWeight.Bold).fontColor(#F1C40F) }.margin({ bottom: 32 }) }现在想加个「NEW」角标——用户首次破纪录时显示提示「这是新纪录」。用 Badge 包住整个 RowBadge({ count: 0, position: BadgePosition.RightTop, style: { fontSize: 10, badgeSize: 28, badgeColor: #E74C3C } }) { // 被标记的内容 Row() { Text( 最高分: ...); } }关键经验Badge 是「容器型」组件——它包裹目标内容在指定位置渲染角标。二、Badge 的两种模式2.1 数字角标countBadge({ count: 5, // 显示数字 5 position: BadgePosition.RightTop, // 右上角 style: { fontSize: 10, badgeSize: 28, badgeColor: #E74C3C } }) { Image($r(app.media.msg)) // 被标记的消息图标 }count 行为count 值显示0不显示角标1–99显示数字≥ 100显示「99」2.2 文本角标valueBadge({ value: NEW, // 显示文本「NEW」 position: BadgePosition.RightTop, style: { fontSize: 10, badgeSize: 28, badgeColor: #E74C3C } }) { Row() { Text( 最高分: 99) } }value 行为value 值显示空字符串不显示角标‘NEW’显示「NEW」‘HOT’显示「HOT」实战经验数字用 count文本用 value——不能同时设同时设以 value 为准。2.3 position 位置position: BadgePosition.RightTop // 右上最常用 position: BadgePosition.Right // 右侧垂直居中位置适用RightTop图标右上红点、NEW 角标Right列表项右侧「未读 5」标记三、用 Badge 改造最高分行3.1 加 NEW 角标Builder MainMenuView() { Column() { Spacer().height(15%) Text().fontSize(72).margin({ bottom: 8 }) Text(猫猫大作战).fontSize(36).fontWeight(FontWeight.Bold).fontColor(#2C3E50).margin({ bottom: 8 }) Text(合并进化 · 策略消除).fontSize(16).fontColor(#95A5A6).margin({ bottom: 48 }) // 最高分Badge 包裹加 NEW 角标 if (this.highScore 0) { Badge({ value: this.isNewRecord ? NEW : , // 新纪录显示 NEW position: BadgePosition.RightTop, style: { fontSize: 10, badgeSize: 28, badgeColor: #E74C3C, textColor: #FFFFFF } }) { Row() { Text( 最高分: ).fontSize(16).fontColor(#F1C40F) Text(this.highScore.toString()).fontSize(20).fontWeight(FontWeight.Bold).fontColor(#F1C40F) } .margin({ bottom: 32 }) } } // 开始游戏按钮 Button(开始游戏) .width(70%).height(56) .fontSize(20).fontWeight(FontWeight.Bold) .fontColor(#FFFFFF).backgroundColor(#2ECC71) .borderRadius(28) .shadow({ radius: 8, color: rgba(46, 204, 113, 0.4), offsetY: 4 }) .onClick(() { this.startGame(); }) Spacer().height(24) // 规则面板第 25 篇 Scroll() { /* ... */ }.height(180) Spacer() } .width(100%).height(100%) .linearGradient({ direction: GradientDirection.Bottom, colors: [[#E8F4F8, 0.0], [#D6EEF5, 0.5], [#C9E8F2, 1.0]] }) .alignItems(HorizontalAlign.Center) }3.2 isNewRecord 状态控制State isNewRecord: boolean false; endGame() { this.gameState GameState.GAME_OVER; if (this.score this.highScore) { this.highScore this.score; this.isNewRecord true; // 标记新纪录 } this.clearTimers(); } // 用户回到主菜单后3 秒自动隐藏 NEW 角标 startGame() { if (this.isNewRecord) { setTimeout(() { this.isNewRecord false; }, 3000); } /* ... */ }执行流程破纪录 →isNewRecord true→ Badge 显示「NEW」。回主菜单看到「 最高分: 99 [NEW]」。3 秒后isNewRecord false→ Badge value 变空 → 角标消失。四、style 样式定制4.1 完整 style 参数style: { fontSize: 10, // 角标文字字号 badgeSize: 28, // 角标直径圆形 badgeColor: #E74C3C, // 角标背景色 textColor: #FFFFFF, // 角标文字色 borderColor: #FFFFFF, // 角标边框色 borderWidth: 1 // 角标边框宽 }参数作用默认fontSize文字字号10badgeSize角标圆形直径16badgeColor背景色红色textColor文字色白色borderColor边框色无borderWidth边框宽04.2 不同场景的 style 配置场景badgeSizebadgeColorfontSize未读消息红点8#E74C3C8未读数字角标20#E74C3C12NEW 角标28#E74C3C10HOT 角标32#F39C1211倒计时角标36#2ECC7110实战经验角标文字 ≤ 3 字符用 badgeSize 284 字符用 32——否则文字溢出角标圆形。五、Badge vs Stack 手搓红点5.1 Stack 手搓红点Stack({ alignContent: Alignment.TopEnd }) { Image($r(app.media.msg)) Text(5) .fontSize(10).fontColor(#FFFFFF) .backgroundColor(#E74C3C) .borderRadius(10) .padding(2) .margin({ top: -4, right: -4 }) } .width(40).height(40)5.2 Badge 简化版Badge({ count: 5, position: BadgePosition.RightTop, style: { fontSize: 10, badgeSize: 20, badgeColor: #E74C3C } }) { Image($r(app.media.msg)) } .width(40).height(40)5.3 取舍维度BadgeStack 手搓代码量少多可定制性中固定 style 参数高任意属性99 自动转换✅❌ 要自己写复杂动效呼吸/弹跳❌✅实战经验标准角标用 Badge——99 转换、位置对齐都内置要动效或异形角标用 Stack 手搓。六、踩坑提示6.1 Badge 包裹的组件没设尺寸// ❌ 错误Row 没 widthBadge 角标位置漂 Badge({ value: NEW, position: BadgePosition.RightTop }) { Row() { Text(...) } // wrap_content位置不定 } // ✅ 正确给被包裹组件设尺寸或用 padding 固定 Badge({ value: NEW, position: BadgePosition.RightTop }) { Row() { Text(...) }.width(120) }6.2 count 与 value 同时设// ⚠️ 同时设value 优先count 被忽略 Badge({ count: 5, value: NEW }) { /* ... */ } // 显示「NEW」不显示 56.3 Badge 嵌套 Badge// ❌ 错误嵌套 Badge角标重叠混乱 Badge({ count: 1 }) { Badge({ count: 2 }) { Image() } } // ✅ 正确只包一层 Badge({ count: 2 }) { Image() }七、性能与最佳实践标准角标用 Badge——99 自动转换、位置对齐内置。数字用 count文本用 value——别同时设。被包裹组件设固定尺寸——避免角标位置漂移。要动效或异形角标用 Stack 手搓——Badge 不支持自定义动效。角标文字 ≤ 3 字符用 badgeSize 28——否则文字溢出。总结本篇我们从 Badge 角标切入掌握了两种模式count 数字 / value 文本、position 位置与 style 样式定制、与 Stack 手搓的取舍三大要点并给出了最高分 NEW 角标完整代码。核心要点Badge 是容器型组件count 自动 99要动效用 Stack 手搓。下一篇我们将拆解 Image 资源引用——$r 与 $rawfile 的区别。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源「猫猫大作战」项目源码本仓库entry/src/main/ets/pages/Index.etsBadge 角标组件官方指南BadgePosition 位置枚举官方参考ArkUI 信息标记最佳实践开源鸿蒙跨平台社区HarmonyOS 开发者官方文档首页系列索引本仓库articles/INDEX.md