为一篇讲解 HarmonyOS 7 用 Grid 做九宫格菜单细节的中文技术文章生成一张对比图,风格

为一篇讲解 HarmonyOS 7 用 Grid 做九宫格菜单细节的中文技术文章生成一张手绘流程图。

为一篇讲解 HarmonyOS 7 用 Grid 做九宫格菜单细节的中文技术文章生成一张手绘笔记风信

前言

九宫格菜单看起来只是把入口排整齐,但它其实承担了首页导航效率。用户要找扫一扫、付款码、账单、客服,第一眼扫不到,就会觉得页面不好用。

HarmonyOS7 里用 Grid 做九宫格很快,几行代码就能铺出来。真正要注意的是:入口有没有稳定身份,角标会不会挤压标题,禁用态是不是只改了颜色。

工具入口不要只存标题,至少要有业务 id、展示文案、状态字段和点击目标。

为什么这个问题经常被写乱

Grid 做九宫格菜单的几个细节 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。

所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

先设计入口数据

我一般不会直接在 GridItem 里写死一个个 Text。入口一多,硬编码很快失控。

更稳的方式是先设计一张配置表:

字段 用途 为什么需要
id 稳定身份 做 key、埋点、跳转都能用
title 展示文案 运营可改,不影响组件身份
iconText 图标占位 示例里用文字代替图标,真实项目可换资源
badge 角标 新功能、未读数、活动提示都能表达
disabled 是否可点 权限不足或功能未开放时使用

九宫格不是“九个格子”,它更像一张入口配置表。UI 只是把这张表渲染出来。

先把页面目标想清楚

在真正写代码之前,先别急着盯着 API。更有用的做法是先想清楚:这个页面到底想解决什么问题,用户最在意的反馈是什么,哪些状态必须一直保持一致。

当你先把这条主线想明白,再回头看组件和状态设计,很多选择都会顺理成章。对小白来说,这一步尤其重要,因为它能帮你从“照着抄”慢慢过渡到“看得懂、改得动”。

完整 ArkUI 示例

下面这个例子用四列网格展示常用工具,包含角标、灰置入口和点击选中反馈。

interface ToolMenuItem {
  id: number
  title: string
  iconText: string
  badge: string
  disabled: boolean
}

@Entry
@Component
struct ToolGridPage {
  @State selectedId: number = 0
  private menus: ToolMenuItem[] = [
    { id: 1, title: '扫一扫', iconText: '扫', badge: '', disabled: false },
    { id: 2, title: '付款码', iconText: '付', badge: '', disabled: false },
    { id: 3, title: '账单', iconText: '账', badge: '3', disabled: false },
    { id: 4, title: '客服', iconText: '客', badge: '', disabled: false },
    { id: 5, title: '发票', iconText: '票', badge: '', disabled: false },
    { id: 6, title: '积分', iconText: '积', badge: '新', disabled: false },
    { id: 7, title: '会员', iconText: '会', badge: '', disabled: false },
    { id: 8, title: '更多', iconText: '...', badge: '', disabled: true }
  ]

  build() {
    Column({ space: 10 }) {
      Text('常用工具')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .width('100%')

      Grid() {
        ForEach(this.menus, (item: ToolMenuItem) => {
          GridItem() {
            Stack({ alignContent: Alignment.TopEnd }) {
              Column({ space: 8 }) {
                Text(item.iconText)
                  .fontSize(18)
                  .fontWeight(FontWeight.Bold)
                  .fontColor(item.disabled ? '#AAAAAA' : '#1E88E5')
                  .width(42)
                  .height(42)
                  .textAlign(TextAlign.Center)
                  .backgroundColor(item.disabled ? '#F0F0F0' : '#EAF3FF')
                  .borderRadius(12)
                Text(item.title)
                  .fontSize(13)
                  .fontColor(item.disabled ? '#AAAAAA' : '#222222')
                  .maxLines(1)
                  .textOverflow({ overflow: TextOverflow.Ellipsis })
              }
              .justifyContent(FlexAlign.Center)
              .width('100%')
              .height('100%')

              if (item.badge.length > 0) {
                Text(item.badge)
                  .fontSize(10)
                  .fontColor(Color.White)
                  .padding({ left: 5, right: 5, top: 2, bottom: 2 })
                  .backgroundColor('#E53935')
                  .borderRadius(8)
              }
            }
          }
          .height(92)
          .backgroundColor(this.selectedId === item.id ? '#F1F7FF' : Color.White)
          .borderRadius(10)
          .enabled(!item.disabled)
          .onClick(() => {
            this.selectedId = item.id
          })
        }, (item: ToolMenuItem) => item.id.toString())
      }
      .columnsTemplate('1fr 1fr 1fr 1fr')
      .columnsGap(10)
      .rowsGap(10)
    }
    .padding(16)
    .backgroundColor('#F6F7FB')
  }
}

把关键代码一段段拆开

columnsTemplate('1fr 1fr 1fr 1fr') 表示四列平均分。手机首页常见工具入口用四列比较舒服,信息密度够,又不至于每格太窄。

Stack 只用来处理角标叠放,主体图标和标题仍然交给 Column。这样写的好处是:角标不会参与普通布局,也不会把标题挤下去。

.enabled(!item.disabled) 很关键。禁用态不是只把文字改灰,还要真的禁止点击。否则用户看到灰色入口仍然能点,会以为页面坏了。

selectedId 是轻量点击反馈。真实项目里,你可能点击后立即跳转,不一定需要保留选中态。但在调试埋点或做轻反馈时,这个字段很直观。

常见问题

有些同学会用标题做 key,比如 (item) => item.title。这在测试阶段看不出问题,但运营改“付款码”为“收付款”以后,key 也变了。用业务 id 更稳。

角标也不要写进标题里,比如“账单 3”。这样后面想单独改角标颜色、位置或展示规则会很麻烦。标题是标题,角标是角标,状态字段分开,UI 才好维护。

如果入口数量不是 8 个,也不要为了凑满九宫格硬塞空项。可以让最后一行自然留白,或者用“更多”承接低频入口。

新手最容易踩的坑

这一类示例最容易让人产生错觉:界面出来了,就以为已经掌握了。其实真正容易出问题的地方,通常都在效果之外,比如状态有没有收拢、失败后怎么兜底、以后要扩展时会不会牵一发动全身。

所以你练这篇内容时,别只看“现在能不能跑”,还要继续看“以后好不好改”。能把这个习惯养起来,你写出来的页面会比单纯照着示例拼出来的页面稳很多。

放进真实项目还要补什么

示例代码的重点是把核心思路讲明白,所以很多工程化细节会故意省掉。真正落到项目里时,你通常还要继续补接口联动、异常处理、边界保护、资源抽离,以及和其他页面状态之间的配合。

写在最后

比较稳的做法是分三步走:先把结构和职责立住,再把真实业务接进去,最后再优化视觉和交互体验。这样改出来的页面不只是“能演示”,而是真的更接近可以长期维护的业务代码。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐