暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

157.[HarmonyOS NEXT 实战案例一:Grid] 基础网格布局:打造精美电商商品列表

原创 若城 2025-06-29
124

[HarmonyOS NEXT 实战案例一:Grid] 基础网格布局:打造精美电商商品列表

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

1. Grid组件概述

在HarmonyOS NEXT的ArkUI框架中,Grid组件是一种强大的网格容器,它与GridItem子组件一起使用,可以创建灵活的网格布局。网格布局是由"行"和"列"分割的单元格组成,通过指定"项目"所在的单元格,可以实现各种各样的布局效果。

1.1 Grid与GridItem的关系

  • Grid:网格容器组件,用于设置网格布局相关参数
  • GridItem:网格子项组件,定义子组件相关特征
  • Grid的子组件必须是GridItem组件

1.2 Grid组件的主要特性

特性 描述
自定义行列数 可以通过rowsTemplate和columnsTemplate属性设置网格的行数和列数
尺寸占比控制 可以控制每行每列的尺寸占比
子组件跨行列 可以设置子组件横跨几行或几列
布局方向 支持垂直和水平布局
间距控制 可以设置行间距和列间距
滚动能力 支持构建可滚动的网格布局

2. 电商商品列表实战

在本案例中,我们将使用Grid和GridItem组件创建一个电商应用的商品列表页面,展示Apple Store的产品。

2.1 页面结构概览

我们的电商商品列表页面包含以下几个部分:

  1. 顶部标题栏:显示应用名称和操作按钮
  2. 分类标签:显示商品分类和查看更多选项
  3. 商品网格:使用Grid和GridItem展示商品信息
  4. 底部导航栏:提供应用的主要导航选项

2.2 数据模型定义

首先,我们定义商品数据模型:

interface Product { id: number, name: string, price: number, image: Resource, discount?: number }

然后,创建商品数据数组:

@State products:Product[] = [ { id: 1, name: 'iPhone 15 Pro', price: 7999, image: $r('app.media.phone'), discount: 10 }, { id: 2, name: 'MacBook Pro', price: 12999, image: $r('app.media.big15') }, { id: 3, name: 'iPad Air', price: 4399, image: $r('app.media.big14'), discount: 5 }, // 更多商品... ]

2.3 顶部标题栏实现

// 顶部标题栏 Row() { Text('Apple Store') .fontSize(24) .fontWeight(FontWeight.Bold) .fontColor('#1D1D1F') Blank() Button() { Image($r('app.media.search_icon')) .width(24) .height(24) } .width(40) .height(40) .borderRadius(20) .backgroundColor('#F5F5F7') Button() { Image($r('app.media.cart_icon')) .width(24) .height(24) } .width(40) .height(40) .borderRadius(20) .backgroundColor('#F5F5F7') .margin({ left: 12 }) } .width('100%') .padding({ left: 20, right: 20, top: 10, bottom: 10 }) .backgroundColor('#FFFFFF')

2.4 分类标签实现

// 分类标签 Row() { Text('热门商品') .fontSize(18) .fontWeight(FontWeight.Medium) .fontColor('#1D1D1F') Blank() Text('查看全部') .fontSize(14) .fontColor('#007AFF') } .width('100%') .padding({ left: 20, right: 20, top: 16, bottom: 16 }) .backgroundColor('#FFFFFF')

3. Grid网格布局实现

3.1 Grid容器配置

Grid() { // GridItem子项... } .columnsTemplate('1fr 1fr') // 两列布局 .columnsGap(16) // 列间距 .rowsGap(16) // 行间距 .width('100%') .layoutWeight(1) .padding({ left: 20, right: 20, bottom: 20 }) .backgroundColor('#F2F2F7')

在这个配置中:

  • columnsTemplate('1fr 1fr'):设置两列布局,每列占比相等
  • columnsGap(16):设置列间距为16vp
  • rowsGap(16):设置行间距为16vp

3.2 GridItem商品卡片实现

我们使用ForEach循环遍历商品数据,为每个商品创建一个GridItem:

ForEach(this.products, (product:Product) => { GridItem() { Column() { // 商品图片容器 Stack({ alignContent: Alignment.TopEnd }) { Image(product.image) .width('100%') .height(120) .objectFit(ImageFit.Contain) .backgroundColor('#F8F8F8') .borderRadius(12) // 折扣标签 if (product.discount) { Text(`-${product.discount}%`) .fontSize(12) .fontColor('#FFFFFF') .backgroundColor('#FF3B30') .padding({ left: 8, right: 8, top: 4, bottom: 4 }) .borderRadius(8) .margin({ top: 8, right: 8 }) } } .width('100%') .height(120) // 商品信息 Column() { Text(product.name) .fontSize(14) .fontWeight(FontWeight.Medium) .fontColor('#1D1D1F') .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) .margin({ top: 12 }) Row() { if (product.discount) { Text(${(product.price * (100 - product.discount) / 100).toFixed(0)}`) .fontSize(16) .fontWeight(FontWeight.Bold) .fontColor('#FF3B30') Text(${product.price}`) .fontSize(12) .fontColor('#8E8E93') .decoration({ type: TextDecorationType.LineThrough }) .margin({ left: 4 }) } else { Text(${product.price}`) .fontSize(16) .fontWeight(FontWeight.Bold) .fontColor('#1D1D1F') } Blank() Button() { Image($r('app.media.add_icon')) .width(16) .height(16) .fillColor('#FFFFFF') } .width(28) .height(28) .borderRadius(14) .backgroundColor('#007AFF') } .width('100%') .margin({ top: 8 }) } .alignItems(HorizontalAlign.Start) .width('100%') } .width('100%') .padding(12) .backgroundColor('#FFFFFF') .borderRadius(16) .shadow({ radius: 8, color: 'rgba(0, 0, 0, 0.1)', offsetX: 0, offsetY: 2 }) } .onClick(() => { console.log(`点击了商品: ${product.name}`) }) })

每个GridItem包含:

  1. 商品图片:使用Stack布局,支持在右上角显示折扣标签
  2. 商品名称:支持最多显示两行,超出部分使用省略号
  3. 价格信息:显示原价和折扣价(如果有折扣)
  4. 添加按钮:用于将商品添加到购物车

3.3 底部导航栏实现

// 底部导航栏 Row() { Column() { Image($r('app.media.home_icon')) .width(24) .height(24) .fillColor('#007AFF') Text('首页') .fontSize(12) .fontColor('#007AFF') .margin({ top: 4 }) } .layoutWeight(1) // 其他导航项... } .width('100%') .height(60) .backgroundColor('#FFFFFF') .borderColor('#E5E5EA') .borderWidth({ top: 1 })

4. Grid组件的关键属性详解

4.1 行列设置

属性 描述 示例
columnsTemplate 设置网格布局的列数和每列的尺寸占比 '1fr 2fr':两列布局,第二列是第一列的两倍宽
rowsTemplate 设置网格布局的行数和每行的尺寸占比 '1fr 1fr 1fr':三行布局,每行高度相等
columnsGap 设置列间距 columnsGap(16)
rowsGap 设置行间距 rowsGap(16)

4.2 GridItem定位属性

属性 描述 示例
rowStart 设置起始行号 rowStart(1)
rowEnd 设置结束行号 rowEnd(3)
columnStart 设置起始列号 columnStart(2)
columnEnd 设置结束列号 columnEnd(4)

4.3 布局方向

Grid() { // 子项... } .layoutDirection(GridDirection.Row) // 水平方向布局

GridDirection枚举值:

  • GridDirection.Row:水平方向布局(默认)
  • GridDirection.Column:垂直方向布局

5. 布局技巧与最佳实践

5.1 响应式网格布局

在不同屏幕尺寸下,可以动态调整列数:

// 根据屏幕宽度调整列数 let columns = '1fr 1fr'; if (screenWidth >= 600) { columns = '1fr 1fr 1fr'; } if (screenWidth >= 840) { columns = '1fr 1fr 1fr 1fr'; } Grid() { // 子项... } .columnsTemplate(columns)

5.2 商品卡片设计技巧

  1. 阴影效果:使用shadow属性为卡片添加阴影,增强立体感
  2. 圆角处理:为卡片和图片添加borderRadius,使界面更加圆润
  3. 折扣标签:使用条件渲染显示折扣标签,突出促销商品
  4. 文本溢出处理:使用maxLines和textOverflow处理长文本

5.3 网格间距优化

适当的网格间距可以提升用户体验:

  • 列间距(columnsGap):通常设置为12-20vp
  • 行间距(rowsGap):通常设置为16-24vp

6. 总结

在本教程中,我们学习了如何使用HarmonyOS NEXT的Grid和GridItem组件创建一个电商商品列表页面。我们详细讲解了Grid组件的基本概念、主要属性和使用方法,以及如何通过合理的布局和样式设计,打造美观实用的商品卡片。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论