HarmonyOS应用开发实战:猫猫大作战-Button 颜色系统与视觉语义
前言上一篇我们用RowSpacer搭好了底部双按钮栏但只是把按钮「摆上去」——按钮的视觉语义、圆角尺寸、点击反馈都还没讲透。这一篇专攻底部栏里那个灰色的「暂停」按钮把Button的颜色系统、圆角档位、stateEffect点击反馈、buttonStyle视觉态四大要点一次讲透。本篇以「猫猫大作战」底部暂停按钮为锚点。读完本篇你将能独立写出主操作绿色按钮、次要操作灰色按钮、危险操作红色按钮三种视觉语义的 Button并掌握圆角档位与点击反馈的搭配套路。提示本系列不讲 ArkTS 基础语法与环境搭建假设你已跟完第 1–18 篇。本篇是 Button 组件的进阶样式篇。一、场景拆解暂停按钮的视觉规格打开entry/src/main/ets/pages/Index.ets的GameView底部栏暂停按钮代码如下// 来源entry/src/main/ets/pages/Index.ets GameView() 底部栏 Button(暂停) .width(100) .height(44) .fontSize(15) .fontColor(#FFFFFF) .backgroundColor(#95A5A6) .borderRadius(22) .onClick(() { this.pauseGame(); })这条按钮的视觉规格拆解属性值含义width100按钮宽 100vpheight44按钮高 44vpfontSize15文字字号 15vpfontColor#FFFFFF白色文字backgroundColor#95A5A6灰色背景borderRadius22圆角 height/2 胶囊形关键经验Button 的视觉规格 尺寸 圆角 颜色 字号四大要素缺一不可。二、Button 的颜色系统2.1 色彩语义三档ArkUI 没有强制按钮颜色规范但业界有共识——按钮颜色 用户引导语义颜色hex用途本项目位置主操作成功绿#2ECC71引导用户首选的操作开始游戏按钮次要操作中性灰#95A5A6不强推、随时可点暂停按钮危险操作警告红#E74C3C不可逆、需谨慎重新开始按钮中性重置提醒橙#F39C12介于次要与危险之间暂停弹窗的「重新开始」提示「重新开始」在底部栏是红色在暂停弹窗里是橙色——底部栏的重新开始会清空进度危险暂停弹窗的重新开始同样清空进度但用户已经在暂停态意图更明确所以用更温和的橙色。2.2 字色对比度.fontColor(#FFFFFF) // 白字 .backgroundColor(#95A5A6) // 灰底对比度公式WCAG 建议正文与背景对比度 ≥ 4.5:1。本项目按钮配色对比度背景字色对比度达标灰#95A5A6白#FFFFFF2.7:1❌ 低于 4.5红#E74C3C白#FFFFFF3.3:1❌绿#2ECC71白#FFFFFF1.9:1❌踩坑按 WCAG 严格标准这些按钮都不达标。但大字号≥18pt 或 14pt 粗体放宽到 3:1本项目按钮字号 15vp 不算大字。实战经验游戏类应用色彩对比度可适当放宽——视觉风格优先于无障碍标准。生产环境建议把灰底调深到#7F8C8D对比度 4.6:1 达标。2.3 纯色 vs 渐变// 写法 1纯色本项目 .backgroundColor(#95A5A6) // 写法 2线性渐变更立体 .linearGradient({ direction: GradientDirection.Bottom, colors: [[#BDC3C7, 0.0], [#95A5A6, 1.0]] }) // 写法 3深浅两段最立体 .linearGradient({ direction: GradientDirection.Bottom, colors: [[#AAB7B8, 0.0], [#95A5A6, 0.5], [#7F8C8D, 1.0]] })方案视觉性能纯色平面最优渐变立体中等三段渐变最立体略低实战经验移动端按钮建议纯色——渐变在小屏上立体感不明显但消耗 GPU 填充率。本项目全部用纯色。三、borderRadius 圆角档位3.1 圆角档位表ArkUI 的borderRadius是一个统一圆角值不同档位视觉差异大圆角值视觉适用本项目位置0直角表格、卡片底—4小圆角输入框、Tag—8中圆角卡片、面板—12大圆角棋盘背景Stack 棋盘22height/2胶囊形按钮暂停/重新开始按钮999 / height超大圆角胶囊头像、圆形按钮—关键公式胶囊形圆角 height / 2。本项目按钮 height44圆角22正好胶囊形。3.2 圆角不一致的踩坑// ❌ 错误圆角 20 ≠ height/222左右两端不是半圆 Button(暂停).height(44).borderRadius(20) // ✅ 正确圆角 height/2左右两端是完美半圆 Button(暂停).height(44).borderRadius(22)视觉差异微小但可察觉——圆角 20 时两端略有「直角感」22 时端到端是平滑半圆。3.3 四角不同圆角// 写法 1统一圆角本项目推荐 .borderRadius(22) // 写法 2四角分别设置 .borderRadius({ topLeft: 22, topRight: 22, bottomLeft: 22, bottomRight: 22 }) // 写法 3只圆顶部两角卡片标题区 .borderRadius({ topLeft: 12, topRight: 12, bottomLeft: 0, bottomRight: 0 })实战经验统一圆角用数字写法写法 1四角不同才用对象写法写法 2、3。对象写法更冗长但可读性更好团队协作时统一规范。四、stateEffect 点击反馈4.1 默认 stateEffectButton(暂停) .backgroundColor(#95A5A6) // 默认 stateEffecttrue按下时背景色变浅 30%ArkUI 的Button有个stateEffect属性默认true——按下时按钮会有视觉反馈背景色微微变浅。stateEffect按下视觉适用true默认背景变浅有按压感普通按钮false无变化按下「无感」禁用按钮、加载中按钮4.2 关闭 stateEffect 的场景// 加载中按钮禁用点击反馈 Button(加载中...).stateEffect(false).enabled(false) // 禁用按钮灰化 无反馈 Button(不可用).stateEffect(false).backgroundColor(#ECF0F1).fontColor(#BDC3C7)实战经验禁用按钮同时设stateEffect(false)enabled(false)——前者去掉按压反馈后者阻止点击事件。4.3 自定义按压反馈ArkUI 内置的stateEffect反馈较微弱要更强反馈可监听 touch 事件改透明度Button(暂停) .backgroundColor(#95A5A6) .opacity(this.isPressed ? 0.7 : 1.0) // 按下 0.7松开 1.0 .onTouch((event) { if (event.type TouchType.Down) this.isPressed true if (event.type TouchType.Up) this.isPressed false })关键经验简单按钮用默认 stateEffect强反馈按钮用 opacity onTouch 自定义。本系列第 30 篇会专讲 AttributeModifier 复用按钮样式。五、buttonStyle 视觉态5.1 ButtonStyle 枚举ArkUI 的Button有三种buttonStyleAPI 11ButtonStyle视觉适用NORMAL默认矩形/胶囊纯色背景通用操作按钮CAPSULE强制胶囊形自动 borderRadius移动端主操作CIRCLE强制圆形widthheight浮动按钮 FAB、图标按钮// 写法 1NORMAL 手动 borderRadius22本项目等效 Button(暂停, { type: ButtonType.Normal }) .height(44).borderRadius(22) // 写法 2CAPSULE 自动胶囊最简 Button(暂停, { type: ButtonType.Capsule }) .height(44) // borderRadius 自动 height/2 // 写法 3CIRCLE 圆形按钮FAB Button(, { type: ButtonType.Circle }) .width(56).height(56) .backgroundColor(#2ECC71)关键经验胶囊按钮用ButtonType.Capsule最简——不用手算 borderRadius。本项目用ButtonType.Normal borderRadius22 也能达到胶囊形但 Capsule 更规范。5.2 ButtonType 完整对照// ButtonType.Normal矩形需手动设 borderRadius Button(A, { type: ButtonType.Normal }).borderRadius(8) // ButtonType.Capsule胶囊形自动圆角 Button(B, { type: ButtonType.Capsule }) // ButtonType.Circle圆形widthheight 时自动圆 Button(C, { type: ButtonType.Circle }).width(48).height(48)ButtonType自动圆角需设 width/height视觉Normal否是矩形/圆角矩形Capsule是height/2是胶囊Circle是width/2是且 widthheight圆六、按钮组合底部栏双按钮配色回顾底部栏完整按钮配置// 来源entry/src/main/ets/pages/Index.ets GameView() 底部栏 Row() { // 暂停灰色次要操作 Button(暂停) .width(100).height(44) .fontSize(15).fontColor(#FFFFFF) .backgroundColor(#95A5A6) .borderRadius(22) .onClick(() { this.pauseGame(); }) Spacer() // 重新开始红色危险操作 Button(重新开始) .width(100).height(44) .fontSize(15).fontColor(#FFFFFF) .backgroundColor(#E74C3C) .borderRadius(22) .onClick(() { this.clearTimers(); this.startGame(); }) } .width(100%) .padding({ left: 24, right: 24, bottom: 24, top: 12 })两按钮差异表维度暂停重新开始背景灰#95A5A6红#E74C3C含义次要操作危险操作点击pauseGameclearTimers startGame失误成本低可继续高进度清零七、完整代码暂停按钮 pauseGame// 来源entry/src/main/ets/pages/Index.ets pauseGame() { if (this.gameState GameState.PLAYING) { this.gameState GameState.PAUSED; } } // 底部栏暂停按钮本篇重点 Builder GameView() { Column() { this.GameHUD() Column() { /* 预告 棋盘 */ }.alignItems(HorizontalAlign.Center) Spacer() Row() { Button(暂停) .width(100).height(44) .fontSize(15).fontColor(#FFFFFF) .backgroundColor(#95A5A6) .borderRadius(22) .onClick(() { this.pauseGame(); }) Spacer() Button(重新开始) .width(100).height(44) .fontSize(15).fontColor(#FFFFFF) .backgroundColor(#E74C3C) .borderRadius(22) .onClick(() { this.clearTimers(); this.startGame(); }) } .width(100%) .padding({ left: 24, right: 24, bottom: 24, top: 12 }) } .width(100%).height(100%) .linearGradient({ direction: GradientDirection.Bottom, colors: [[#E8F4F8, 0.0], [#D6EEF5, 0.5], [#C9E8F2, 1.0]] }) .alignItems(HorizontalAlign.Center) }八、踩坑提示8.1 Button 不设 width/height 会塌缩// ❌ 错误只设文字不设尺寸 Button(暂停).fontSize(15) // Button 默认 wrap_content宽 文字宽 padding高 文字高 padding很小 // ✅ 正确显式设尺寸 Button(暂停).width(100).height(44)8.2 backgroundColor 不生效// ❌ 错误Button 用了 Capsule 类型但没设 backgroundColor显示默认蓝 Button(暂停, { type: ButtonType.Capsule }) // 默认蓝主题色 // ✅ 正确显式设 backgroundColor Button(暂停, { type: ButtonType.Capsule }) .backgroundColor(#95A5A6)8.3 borderRadius 与 ButtonType 冲突// ❌ 错误Capsule 自动圆角再手动设 borderRadius 会冲突 Button(A, { type: ButtonType.Capsule }).borderRadius(10) // 实际渲染以 Capsule 自动圆角为准borderRadius 被忽略 // ✅ 正确Capsule 不设 borderRadius要自定义圆角用 Normal Button(A, { type: ButtonType.Normal }).borderRadius(10)8.4 onClick 丢失 this// ❌ 错误普通函数 this 不指向组件 Button(暂停).onClick(function () { this.pauseGame() }) // ✅ 正确箭头函数保留外层 this Button(暂停).onClick(() { this.pauseGame() })本系列第 38 篇会专讲箭头函数 this 绑定。九、调试技巧按钮颜色看不到检查 backgroundColor 是否被父容器的 backgroundColor 覆盖检查 opacity 是否为 0。按钮形状不对Capsule 类型下别手动设 borderRadius要自定义圆角改用 Normal。点击无反馈默认 stateEffecttrue 会有按压反馈若关闭了可通过 onTouch 改 opacity 自定义反馈。按钮太小点不到HarmonyOS 建议最小可点击区域 48×48vp本项目 100×44vp 宽度够高度略低可调到 48vp。十、性能与最佳实践胶囊按钮用 ButtonType.Capsule——自动圆角不用手算 borderRadius。颜色遵循语义——绿主操作、灰次要、红危险、橙中性。对比度 ≥ 4.5:1——深底白字或浅底深字避免中灰底白字。禁用按钮双设——stateEffect(false) enabled(false) 同时设。强反馈用 opacity onTouch——默认 stateEffect 反馈微弱。最小点击区 48vp——低于 48vp 容易误触。总结本篇我们从暂停按钮样式切入掌握了Button 颜色语义四档绿/灰/红/橙、borderRadius 胶囊形公式 height/2、stateEffect 点击反馈与禁用、**buttonStyle 视觉态Normal/Capsule/Circle**四大要点并给出了暂停按钮 pauseGame 完整代码。核心要点胶囊按钮用 Capsule 最简颜色遵循语义禁用按钮双设 stateEffectenabled最小点击区 48vp。下一篇我们将拆解 SymbolGlyph——用系统符号字体替代 Emoji 的方案。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源「猫猫大作战」项目源码本仓库entry/src/main/ets/pages/Index.etsButton 组件官方指南ButtonType 枚举官方文档borderRadius 圆角属性官方指南ArkUI 无障碍设计最佳实践开源鸿蒙跨平台社区HarmonyOS 开发者官方文档首页系列索引本仓库articles/INDEX.md