ArkUI Grid 组件详解与使用指南

Grid 是 ArkUI 中用于实现网格布局的容器组件,能够以行和列的形式排列子组件。以下是 Grid 组件的详细介绍和使用方法。

基本介绍

Grid 组件特点:

  • 支持固定列数和自适应布局
  • 提供灵活的间距和排列控制
  • 支持滚动显示大量项目
  • 可以实现复杂的网格布局效果

基本使用

1. 简单网格布局

@Entry
@Component
struct SimpleGridExample {
  private data: string[] = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6']

  build() {
    Grid() {
      ForEach(this.data, (item: string) => {
        GridItem() {
          Text(item)
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .width('100%')
            .height('100%')
            .backgroundColor('#f0f0f0')
        }
      }, (item: string) => item)
    }
    .columnsTemplate('1fr 1fr 1fr') // 3等分列
    .rowsTemplate('1fr 1fr') // 2等分行
    .columnsGap(10) // 列间距
    .rowsGap(10) // 行间距
    .height(300)
    .width('100%')
    .margin(10)
  }
}

2. 自适应网格

@Entry
@Component
struct AutoGridExample {
  private data: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']

  build() {
    Grid() {
      ForEach(this.data, (item: string) => {
        GridItem() {
          Text(item)
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .textAlign(TextAlign.Center)
            .width('100%')
            .height('100%')
            .backgroundColor('#e6f7ff')
            .borderRadius(8)
        }
      }, (item: string) => item)
    }
    .maxCount(4) // 每行最多4项
    .minCount(2) // 每行至少2项
    .cellLength(100) // 每个网格项的长度
    .height('100%')
    .width('100%')
    .padding(10)
  }
}

核心功能

1. 网格模板布局

Grid() {
  // GridItems...
}
.columnsTemplate('100px 1fr 2fr') // 第一列固定100px,第二列1份,第三列2份
.rowsTemplate('50px 1fr 50px') // 第一行和第三行固定50px,中间行自适应

2. 网格间距控制

Grid() {
  // GridItems...
}
.columnsGap(12) // 列间距12px
.rowsGap(8) // 行间距8px

3. 滚动网格

Grid() {
  ForEach(Array(20).fill(0).map((_, index) => {
    GridItem() {
      Text(`Item ${index + 1}`)
        // 样式...
    }
  })
}
.columnsTemplate('1fr 1fr 1fr')
.height(400) // 固定高度实现滚动
.width('100%')
.scrollBar(BarState.On) // 显示滚动条

4. 响应式网格

@Entry
@Component
struct ResponsiveGridExample {
  @State gridColumns: string = '1fr 1fr' // 默认2列

  build() {
    Column() {
      // 切换列数按钮
      Row() {
        Button('2列').onClick(() => { this.gridColumns = '1fr 1fr' })
        Button('3列').onClick(() => { this.gridColumns = '1fr 1fr 1fr' })
        Button('4列').onClick(() => { this.gridColumns = '1fr 1fr 1fr 1fr' })
      }
      .margin(10)
      
      // 响应式网格
      Grid() {
        ForEach(Array(12).fill(0).map((_, index) => {
          GridItem() {
            Text(`Item ${index + 1}`)
              // 样式...
          }
        })
      }
      .columnsTemplate(this.gridColumns)
      .rowsGap(10)
      .columnsGap(10)
      .height('80%')
      .width('100%')
    }
  }
}

高级功能

1. 不规则网格项

Grid() {
  // 跨2列的项
  GridItem({ columnStart: 0, columnEnd: 2 }) {
    Text('跨两列')
      // 样式...
  }
  
  // 跨2行的项
  GridItem({ rowStart: 1, rowEnd: 3 }) {
    Text('跨两行')
      // 样式...
  }
  
  // 普通项
  GridItem() {
    Text('普通项')
      // 样式...
  }
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('100px 100px 100px')

2. 网格项动画

@State scaleValue: number = 1

build() {
  Grid() {
    GridItem() {
      Text('点击放大')
        .width('100%')
        .height('100%')
        .onClick(() => {
          animateTo({
            duration: 300,
            curve: Curve.EaseInOut
          }, () => {
            this.scaleValue = this.scaleValue === 1 ? 1.2 : 1
          })
        })
        .scale({ x: this.scaleValue, y: this.scaleValue })
    }
    // 更多GridItems...
  }
  // 网格配置...
}

3. 网格拖拽排序

@Entry
@Component
struct DraggableGridExample {
  @State items: string[] = ['A', 'B', 'C', 'D', 'E', 'F']
  @State draggedIndex: number = -1

  build() {
    Grid() {
      ForEach(this.items, (item: string, index: number) => {
        GridItem() {
          Text(item)
            .width('100%')
            .height('100%')
            .gesture(
              PanGesture({ distance: 5 })
                .onActionStart(() => {
                  this.draggedIndex = index
                })
                .onActionUpdate((event: GestureEvent) => {
                  // 处理拖拽逻辑
                })
                .onActionEnd(() => {
                  this.draggedIndex = -1
                })
            )
        }
        .zIndex(this.draggedIndex === index ? 1 : 0)
      }, (item: string) => item)
    }
    .columnsTemplate('1fr 1fr 1fr')
    .height(400)
    .width('100%')
  }
}

性能优化

1. 复用网格项

Grid() {
  LazyForEach(this.dataSource, (item: ItemData) => {
    GridItem() {
      // 内容...
    }
  }, (item: ItemData) => item.id.toString())
}

2. 固定尺寸网格项

Grid() {
  ForEach(this.data, (item) => {
    GridItem() {
      // 内容...
    }
    .width(100) // 固定宽度
    .height(120) // 固定高度
  })
}

3. 虚拟滚动

Grid() {
  // 大数据集使用虚拟滚动
  Virtualize({ 
    scroller: this.scroller,
    builder: (index: number) => {
      return this.buildGridItem(index)
    },
    count: this.data.length
  })
}
.height(500)
.width('100%')

最佳实践

  1. 合理设计网格结构

    • 根据内容类型选择合适的列数和行高
    • 考虑不同屏幕尺寸的适配
  2. 优化性能

    • 大数据集使用懒加载或虚拟滚动
    • 避免过度复杂的网格项嵌套
  3. 增强用户体验

    • 为网格项添加适当的交互反馈
    • 实现平滑的滚动和动画效果
  4. 响应式设计

    • 根据屏幕宽度动态调整列数
    • 使用相对单位确保布局弹性

实际应用示例

1. 图片网格画廊

@Entry
@Component
struct ImageGridGallery {
  private images = [
    { id: 1, url: $r('app.media.image1') },
    { id: 2, url: $r('app.media.image2') },
    // 更多图片...
  ]

  build() {
    Grid() {
      ForEach(this.images, (image) => {
        GridItem() {
          Image(image.url)
            .width('100%')
            .height('100%')
            .objectFit(ImageFit.Cover)
            .onClick(() => {
              // 处理图片点击
            })
        }
        .aspectRatio(1) // 保持正方形
      }, (image) => image.id.toString())
    }
    .columnsTemplate('1fr 1fr 1fr')
    .columnsGap(5)
    .rowsGap(5)
    .width('100%')
    .padding(10)
  }
}

2. 仪表盘布局

@Entry
@Component
struct DashboardLayout {
  build() {
    Grid() {
      // 顶部指标卡 - 跨3列
      GridItem({ columnStart: 0, columnEnd: 3 }) {
        DashboardCard('总体数据', '1000')
      }
      
      // 左侧图表 - 跨2行
      GridItem({ rowStart: 1, rowEnd: 3 }) {
        DashboardCard('趋势分析', '图表')
      }
      
      // 右侧小指标
      GridItem({ columnStart: 1 }) {
        DashboardCard('今日新增', '120')
      }
      
      GridItem({ columnStart: 2 }) {
        DashboardCard('完成率', '85%')
      }
      
      GridItem({ columnStart: 1, columnEnd: 3 }) {
        DashboardCard('最近活动', '详情')
      }
    }
    .columnsTemplate('1fr 1fr 1fr')
    .rowsTemplate('80px 1fr 1fr')
    .columnsGap(10)
    .rowsGap(10)
    .height('100%')
    .width('100%')
    .padding(10)
  }

  @Builder
  DashboardCard(title: string, value: string) {
    Column() {
      Text(title)
        .fontSize(14)
        .fontColor('#666')
      Text(value)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 8 })
    }
    .width('100%')
    .height('100%')
    .padding(10)
    .backgroundColor('#fff')
    .borderRadius(8)
    .shadow({ radius: 4, color: '#00000020', offsetX: 1, offsetY: 1 })
  }
}

通过合理使用 Grid 组件,可以创建出灵活、高效的网格布局,适用于各种应用场景,如图库、仪表盘、产品列表等。

Logo

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

更多推荐