文章目录
- 一、Grid组件简介
- 二、基础九宫格实现
- 三、Grid核心属性详解
- 3.1 columnsTemplate - 列模板配置
- 3.2 rowsTemplate - 行模板配置
- 3.3 间距控制
- 3.4 滚动支持
- 四、高级九宫格示例
- 五、布局方向与对齐方式
- 六、响应式网格布局
- 七、性能优化建议
- 八、常见问题与解决方案
- 问题1:GridItem不显示
- 问题2:布局错乱
- 问题3:滚动不流畅
- 九、总结
- 十、进一步学习
这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。
一、Grid组件简介
在鸿蒙应用开发中,Grid 组件是一种强大的网格布局容器,能够将子元素按照行和列的网格形式进行排列。与Flex布局相比,Grid 布局更加灵活,特别适合实现九宫格、商品列表、图片墙等规整的布局效果。
二、基础九宫格实现
下面我们来看如何使用 Grid 组件实现一个基础的九宫格布局:
@Entry@Componentstruct GridExample{// 定义九宫格数据privategridData:string[]=['1','2','3','4','5','6','7','8','9']build(){Column(){Grid(){ForEach(this.gridData,(item:string)=>{GridItem(){// 自定义的九宫格项组件GridItemContent({text:item})}})}.columnsTemplate('1fr 1fr 1fr')// 设置3列,每列等宽.rowsGap(12)// 行间距.columnsGap(12)// 列间距}.width('100%').height('100%').padding(12)}}// 九宫格项组件@Componentstruct GridItemContent{@Proptext:stringbuild(){Column(){// 图片组件Image($r('app.media.startIcon')).width(60).height(60).borderRadius(8)// 文本组件Text(this.text).fontSize(16).margin({top:8})}.width('100%').height(120).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor(Color.White).borderRadius(12).shadow({radius:4,color:'#00000020',offsetX:0,offsetY:2})}}运行效果:
关键点说明:
- Grid的直接子元素必须是GridItem:Grid 组件内部需要使用 GridItem 来包裹实际的子元素
- ForEach遍历数据:使用 ForEach 来遍历数组数据,动态生成网格项
- columnsTemplate设置列数:
'1fr 1fr 1fr'表示将父组件宽度平均分成 3 列
三、Grid核心属性详解
3.1 columnsTemplate - 列模板配置
columnsTemplate属性用于定义网格的列数和每列的宽度比例:
// 3列等宽布局.columnsTemplate('1fr 1fr 1fr')// 4列等宽布局.columnsTemplate('1fr 1fr 1fr 1fr')// 不等宽布局:第一列占2份,其余各占1份(总共5份).columnsTemplate('2fr 1fr 1fr 1fr')// 混合单位:固定宽度+自适应.columnsTemplate('100px 1fr 2fr')3.2 rowsTemplate - 行模板配置
类似地,我们可以使用rowsTemplate来定义行的高度:
// 定义3行,高度分别为:100px、自适应、200px.rowsTemplate('100px 1fr 200px')3.3 间距控制
Grid提供了灵活的间距控制属性:
Grid(){// ... GridItem内容}.rowsGap(16)// 行间距16vp.columnsGap(16)// 列间距16vp3.4 滚动支持
当Grid的内容超出容器高度时,会自动显示滚动条:
Grid(){// ... 多个GridItem}.height(400)// 固定高度,超出则滚动.scrollable(ScrollDirection.Vertical)// 垂直滚动四、高级九宫格示例
下面是一个更完整的九宫格应用示例,包含点击事件和动态数据:
@Entry@Componentstruct AdvancedGridExample{// 九宫格数据模型privategridItems:GridItemData[]=[{id:1,title:'相册',icon:$r('app.media.startIcon'),color:'#FF6B6B'},{id:2,title:'音乐',icon:$r('app.media.startIcon'),color:'#4ECDC4'},{id:3,title:'视频',icon:$r('app.media.startIcon'),color:'#45B7D1'},{id:4,title:'文档',icon:$r('app.media.startIcon'),color:'#96CEB4'},{id:5,title:'下载',icon:$r('app.media.startIcon'),color:'#FFEAA7'},{id:6,title:'设置',icon:$r('app.media.startIcon'),color:'#DDA0DD'},{id:7,title:'帮助',icon:$r('app.media.startIcon'),color:'#98D8C8'},{id:8,title:'关于',icon:$r('app.media.startIcon'),color:'#F7DC6F'},{id:9,title:'更多',icon:$r('app.media.startIcon'),color:'#BB8FCE'}]build(){Column(){Text('应用九宫格').fontSize(24).fontWeight(FontWeight.Bold).margin({bottom:20})Grid(){ForEach(this.gridItems,(item:GridItemData)=>{GridItem(){this.buildGridItem(item)}.onClick(()=>{// 处理点击事件this.onItemClick(item)})})}.columnsTemplate('1fr 1fr 1fr').rowsTemplate('1fr 1fr 1fr').rowsGap(15).columnsGap(15).width('90%').aspectRatio(1)// 保持正方形.layoutDirection(GridDirection.Row)}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor('#F5F5F5')}// 构建网格项@BuilderbuildGridItem(item:GridItemData){Column(){Image(item.icon).width(40).height(40).objectFit(ImageFit.Contain)Text(item.title).fontSize(14).margin({top:8}).fontColor('#333333')}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor(Color.White).borderRadius(16).shadow({radius:6,color:'#00000015',offsetX:0,offsetY:3})}// 点击事件处理onItemClick(item:GridItemData){console.log(`点击了:${item.title}`)// 这里可以添加导航逻辑}}// 数据模型接口interfaceGridItemData{id:numbertitle:stringicon:Resource color:string}运行效果:
五、布局方向与对齐方式
Grid 支持多种布局方向和对齐方式:
Grid(){// ... GridItem内容}.layoutDirection(GridDirection.Row)// 按行排列(默认)// .layoutDirection(GridDirection.Column) // 按列排列.justifyContent(FlexAlign.Start)// 主轴起点对齐// .justifyContent(FlexAlign.Center) // 主轴居中对齐// .justifyContent(FlexAlign.End) // 主轴终点对齐// .justifyContent(FlexAlign.SpaceBetween) // 两端对齐// .justifyContent(FlexAlign.SpaceAround) // 环绕对齐.alignItems(ItemAlign.Start)// 交叉轴起点对齐// .alignItems(ItemAlign.Center) // 交叉轴居中对齐// .alignItems(ItemAlign.End) // 交叉轴终点对齐六、响应式网格布局
Grid 组件也支持响应式设计,可以根据屏幕尺寸动态调整列数:
import{display}from'@kit.ArkUI'@Entry@Componentstruct ResponsiveGridExample{@Statecolumns:string='1fr 1fr'// 默认2列@StatescreenWidth:number=0aboutToAppear(){// 根据屏幕宽度动态调整列数constscreenWidth=px2vp(display.getDefaultDisplaySync().width)this.screenWidth=screenWidthif(screenWidth>750){this.columns='1fr 1fr 1fr 1fr'// 大屏:4列}elseif(screenWidth>400){this.columns='1fr 1fr 1fr'// 中屏:3列}else{this.columns='1fr 1fr'// 小屏:2列}}build(){Column(){Text("屏幕宽度vp:"+this.screenWidth).fontSize(30)Grid(){ForEach([1,2,3,4,5,6,7,8,9],(item:number)=>{GridItem(){Text(`Item${item}`).fontSize(16).textAlign(TextAlign.Center)}.height(80)})}.columnsTemplate(this.columns).rowsGap(10).columnsGap(10).width('100%')}}}上述代码在 DevEco Studio 预览器中无法获取到真实的屏幕宽高,返回的可能为 0 或默认值。必须在模拟器或真机上运行才能正确获取。
模拟器上的运行效果:
400vp < 屏幕宽度 < 750vp
屏幕宽度 > 750vp
七、性能优化建议
- 避免过度嵌套:GridItem 内部组件结构尽量简单
- 使用键值优化:ForEach 中为动态数据提供稳定的 key
- 懒加载:对于大量数据的网格,考虑使用 LazyForEach
- 图片优化:网格中的图片使用合适的尺寸和缓存策略
八、常见问题与解决方案
问题1:GridItem不显示
原因:Grid的直接子元素不是GridItem
解决:确保所有直接子元素都用 GridItem 包裹
问题2:布局错乱
原因:columnsTemplate 设置不当
解决:检查fr单位的使用,确保总和合理
问题3:滚动不流畅
原因:网格项内容过于复杂
解决:简化GridItem内部结构,使用缓存
九、总结
Grid 组件是鸿蒙应用开发中实现网格布局的强大工具,特别适合九宫格、商品列表等场景。通过合理使用columnsTemplate、rowsTemplate、间距和对齐属性,可以创建出既美观又实用的界面布局。
核心要点回顾:
- Grid的直接子元素必须是GridItem
- 使用columnsTemplate定义列数和宽度比例
- 通过rowsGap和columnsGap控制间距
- 支持滚动和响应式布局
- 结合ForEach实现动态数据渲染
十、进一步学习
要深入了解 Grid 组件的更多高级特性,建议查阅 官方文档 。
通过掌握 Grid 组件,您将能够轻松应对各种复杂的网格布局需求,提升鸿蒙应用的界面开发效率。