利用 GridContainer 构建响应式栅格布局

在移动端或大屏应用中,我们常常需要在不同宽度下保持内容的整齐排列。ArkUI 的 GridContainer 为我们提供了“栅格系统”能力,帮助你像在网页上一样,轻松实现 12 列、16 列或任意列数的响应式布局。


一、核心概念

  • 列数(columns):将整个容器分成多少列。常见有 12 列、16 列。
  • 断点类型(sizeType):针对不同设备宽度(XS/SM/MD/LG)动态选用不同列宽。
  • 间距(gutter):列与列之间的水平间隙。
  • 边距(margin):栅格系统左右整体留白。

GridContainer 内,每一行用 Row 包裹,行内的每个子组件通过 .useSizeType({...}) 决定它在各个断点下跨几列、偏移多少列。


二、API 速览

interface GridContainerOptions {
  columns?: number | "auto";      // 总列数,默认为 "auto"(自动根据 sizeType 选列数)
  sizeType?: SizeType;            // 当前断点,决定各项 span
  gutter?: number | string;       // 列间距,单位 px 或 vp
  margin?: number | string;       // 左右外边距
}

interface UseSizeTypeConfig {
  span: number;                   // 占用的列数
  offset?: number;                // 左侧偏移的列数
}

declare class GridContainerAttribute extends CommonMethod<GridContainerAttribute> { }
  • .useSizeType({ xs, sm, md, lg })

    • xs/sm/md/lg:分别对应超小、小、中、大设备。
    • 每个配置都是 { span: 列数; offset?: 列数 }

三、示例:6 列布局

下面示例使用 6 列栅格,通过两个按钮切换横竖屏状态,观察同一行内项目跨列变化。

@Entry @Component
struct SixColDemo {
  @State isPortrait: boolean = true;

  build() {
    Column({ space: 12 }) {
      // 按钮控制横竖屏
      Row({ space: 8 }) {
        Button("Portrait")
          .onClick(() => this.isPortrait = true)
        Button("Landscape")
          .onClick(() => this.isPortrait = false)
      }

      // 6 列栅格,gutter 8px,margin 16px
      GridContainer({
        columns: 6,
        sizeType: this.isPortrait ? SizeType.XS : SizeType.LG,
        gutter: 8,
        margin: 16
      }) {
        Row() {
          Text("A")
            .useSizeType({
              xs: { span: 6 },
              lg: { span: 3 }
            })
            .backgroundColor("#FFB6C1")
            .height(40).textAlign(TextAlign.Center);

          Text("B")
            .useSizeType({
              xs: { span: 6 },
              lg: { span: 2, offset: 1 }
            })
            .backgroundColor("#87CEFA")
            .height(40).textAlign(TextAlign.Center);
        }
      }
      .backgroundColor(Color.LightGray)
      .width("100%");
    }
    .padding(10);
  }
}
  • Portrait(XS):两块都各占 6/6 列,满行显示。
  • Landscape(LG):第一块占 3 列,第二块占 2 列并右偏 1 列。

四、示例:12 列等宽卡片

再来一个常见的 12 列等宽卡片网格,使用 Flex 做卡片内排版:

@Entry @Component
struct CardGrid {
  build() {
    GridContainer({
      columns: 12,
      sizeType: SizeType.Auto,
      gutter: "12vp",
      margin: "12vp"
    }) {
      Row() {
        // 生成 8 张卡片
        for (let i = 1; i <= 8; i++) {
          Card(i);
        }
      }
    }
    .width("100%").padding(10);
  }
}

// 卡片组件:在不同断点下占 4/6/3/2 列
@Entry @Component struct Card {
  index: number;

  constructor(index: number) { this.index = index; }

  build() {
    Text(`Card ${this.index}`)
      .useSizeType({
        xs: { span: 12 },
        sm: { span: 6 },
        md: { span: 4 },
        lg: { span: 3 }
      })
      .height(80).backgroundColor("#ffe4b5")
      .textAlign(TextAlign.Center)
      .borderRadius(8)
      .margin({ bottom: 10 });
  }
}
  • XS:每行 1 张(12 列全宽)
  • SM:每行 2 张(6 列各占半宽)
  • MD:每行 3 张(4 列)
  • LG:每行 4 张(3 列)

五、实战建议

  1. 移动优先:先在 xs 下配置,再向上扩展到 smmdlg
  2. 统一间距与边距:根据设计稿统一 guttermargin,保证网格整齐。
  3. 合理偏移:对于需要“居中”或“错位”的元素,可用 offset 精细控制。
  4. 组件化:将可复用模块(卡片、表单项等)封装成组件,内部统一 .useSizeType,外部仅需一行调用。

六、小结

  • GridContainer 能让 ArkUI 拥有 Web 端经典栅格系统;
  • 灵活控制总列、断点、间距与边距,实现多场景响应式布局;
  • 配合 Row.useSizeType 以及组件化,可以在手机、平板、电视等多终端下,都获得整洁的排版效果。

掌握它,ArkUI 界面设计再也不怕各种屏幕尺寸了!

Logo

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

更多推荐