GridRow:栅格容器组件,需与结合其子组件GridCol开发,可以适配不同尺寸的设备,让各个设备可以合理的显示,不用过多去做屏幕适配。
一、GridRow参数:breakpoints、columns和gutter
断点:breakpoint
官方:栅格系统以设备的水平宽度(屏幕密度像素值,单位vp)作为断点依据,定义设备的宽度类型,形成了一套断点规则。开发者可根据需求在不同的断点区间实现不同的页面布局效果。
为了便于理解,通过下面的示例代码进行说明。阅览示例代码可知,brerakpoints是GridRow的参数。values和reference是breakpoints的两个成员变量,这两个变量需要结合使用:
1、WindowSize:若reference的值为BreakpointsReference.WindowSize,也是默认值,此值表示是以设备的宽度作为参照,通过屏宽与values内的每个元素进行比较。跟设备有关,因为不同设备,屏宽可能不同。
屏宽属于[0, 300vp)就是xs,
屏宽属于[300, 600vp)就是sm,
屏宽属于[600, 800vp)就是md,
屏宽属于[800, 1000vp)就lg,
屏宽属于[1000, 1200vp)就是xl,
屏宽属于[1200, +∞)就是xxl
2、ComponentSize:若reference的值为BreakpointsReference.ComponentSize,表示是以容器(GridRow)的尺寸作为参照,通过容器width与value内的每个元素进行比较,比较原理与屏宽一致。
需要注意:因为此时是用容器的尺寸的进行比较,所以与当前的设备就无关了(若按设备百分比设置宽度,那跟屏宽还是有关系的)。
重点说明:在示例代码中,values = ['300vp', '600vp', '800vp', '1000vp', '1200vp'],但values中元素的值是不固定的,理论上只要从小到大排列即可,但这需要跟当前的需求做出相应的调整,因为官方要求最多只能有xs、sm、md、lg、xl、xxl六个断点,所以value中最多只能有五个元素,若只有四个元素,则xxl自动失效,可省去,以此类推,若里面只有一个元素,那就意味着所有情况都只有xs[0, '300vp')和sm['300vp', +∞)两个断点。
span中的xs等断点所传入的值是所占列数,不理解可以暂时先跳过,下面会详细讲解
@Entry
@Component
struct Index {
@State gridRowWidth: number = 200;
colors: Color[] = [Color.Red, Color.Yellow, Color.Pink, Color.Orange, Color.Brown, Color.Blue, Color.Orange, Color.Gray]
build() {
Column() {
GridRow({
breakpoints: {
value: ['300vp', '600vp', '800vp', '1000vp', '1200vp'],
// reference: BreakpointsReference.WindowSize, // 以设备尺寸作为参照,跟设备有关
reference: BreakpointsReference.ComponentSize // 以容器组件尺寸作为参照,绝对尺寸,此处与设备无关
},
direction: GridRowDirection.Row // 排列方式:从左至右
}) {
ForEach(this.colors, (item: Color, index: Number) => {
GridCol({
span: {
xs: 12, //设备/容器组件宽度在【0, 300) 之间,即为xs。 在最小宽度类型设备上,GridCol占据的GridRow中的12列。
sm: 6, // 设备/容器组件宽度在【300, 600) 之间,即为sm。在小宽度类型设备上,GridCol占据的GridRow中的6列。
md: 4, // 设备/容器组件宽度在【600, 800) 之间,即为md。在中等宽度类型设备上,GridCol占据的GridRow中的4列。
lg: 3, // 设备/容器组件宽度在【800, 1000) 之间,即为lg。在大宽度类型设备上,GridCol占据的GridRow中的3列。
xl: 2, // 设备/容器组件宽度在【1000, 1300) 之间,即为xl。在特大宽度类型设备上,GridCol占据的GridRow中的2列。
xxl: 1 // 设备/容器组件宽度在【1200, +∞)之间,即为xxl。在超大宽度类型设备上,GridCol占据的GridRow中的1列。
}
}) {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
.onClick(() => {
this.gridRowWidth += 50; //修改容器组件GridRow的宽度,用于测试,前提:以容器组件为参照
})
}.width('100%').height(50)
}
.backgroundColor(item)
}, (item: Color) => item.toString())
}
.width(`${this.gridRowWidth}vp`)
.height(500)
.backgroundColor('#f5f5f5')
}
.width('100%')
}
}
columns
columns默认值是12,即在不设此参数时,默认12列,也可以自定义
同样通过下面示例代码进行说明:
1、columns是一个复合值类型(number | GridRowColumnOption)。
当columns为number类型时,比如columns: 10,在任何情况下GridRow都被分为10列。下面分别设置GridRow列数为6和10,子元素分别占2列和5列,下面代码就是columns为number类型的示例代码。
当columns类型为GridRowColumnOption时,比如columns: { sm: 4, md: 8 },表示在断点为sm时,GridRow被分为4列;点断为md时,GridRow被分为8列,其他情况默认还是12列。GridRowColumnOption的代码就不做演示了,原理大同小异。
gutter
gutter也是一个复合值类型(Length | GutterOption)。
当gutter为Length类型时,例如:gutter: 20,表示GridCol之间的距离上下左右的距离均为20。
也可以为GutterOption类型,例如:gutter: {x:20, y: 10},表示水平方向间距20,垂直方向间距10。
备注:当一行展示不下时,自动折行。
代码与效果图如下:
@Entry
@Component
struct Index {
colors: Color[] = [
Color.Red, Color.Yellow, Color.Pink, Color.Orange,
Color.Brown, Color.Blue, Color.Yellow, Color.Orange,
Color.Gray, Color.Pink, Color.Orange, Color.Brown];
build() {
Column({space: 30}) {
GridRow({
gutter: 20, // GridCol之间的间距为20,也可以设置为{x:20, y: 10},表示水平方向间距20,垂直方向间距10
columns: 6 // 表示一共把GridRow的宽度分为6列(为了更好理解,可以理解成分为了6份)
}) {
ForEach(this.colors, (item: Color, index: Number) => {
GridCol({
span: 2 // 共6份,此设置表示占2份的宽度, 所以会展示3列
}) {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}.width('100%').height(50)
}
.backgroundColor(item)
}, (item: Color) => item.toString())
}
.width('100%')
.height(500)
.backgroundColor('#f5f5f5')
GridRow({
gutter: {x: 20, y: 10}, // 表示为{x:20, y: 10},表示水平方向间距20,垂直方向间距10
columns: 10 // 10列
}){
ForEach(this.colors, (item: Color, index: number) => {
GridCol({
span: 5 // 共10份,此设置表示占5份的宽度, 所以会展示2列
}) {
Row(){
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}
.backgroundColor(item)
.width('100%')
.height(50)
}
}, (item: Color) => item.toString())
}
.width('100%')
.height(500)
.backgroundColor('#f5f5f5')
}
.width('100%')
}
}
3、columns默认值为12,没传入columns时,栅格布局被分成12列,与断点无关了,如下代码与效果图如下:
@Entry
@Component
struct Index {
colors: Color[] = [
Color.Red, Color.Yellow, Color.Pink, Color.Orange,
Color.Brown, Color.Blue, Color.Yellow, Color.Orange,
Color.Gray, Color.Pink, Color.Orange, Color.Brown];
build() {
Column() {
GridRow() {
ForEach(this.colors, (item: Color, index: Number) => {
GridCol() {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}.width('100%').height(50)
}
.backgroundColor(item)
}, (item: Color) => item.toString())
}
.width('100%')
.height(500)
.backgroundColor('#f5f5f5')
}
.width('100%')
}
}
三、子组件GridCol的参数:span、offset、order
1、span
也是一个复合值类型 (number | GridColColumnOption)。
当span为number类型时,比如span: 4,表示所有情况GridCol都占4列。
当span为GridColColumnOption类型时,如第一份代码中,span{xs: 12}, 表示在对应为xs断点时,当前的GridCol占12列。
2、offset
也是一个复合值类型 (number | GridColColumnOption),表示GridCol相对于前一个GridCol的偏移列数,默认为0。
当类型为number时,GridCol偏移相同列数。例如:offset: 2,偏移量为2列
当类型为GridColColumnOption时,例如:offset: { xs: 1, sm: 2, md: 3, lg: 4 },逻辑与span类型,分断点情况设置的偏移量
当一行的最后偏移量不够时,需要换行继续偏移
3、order
也是一个复合值类型 (number | GridColColumnOption),表示GridCol当前的排序编号,定GridCol排列次序。当GridCol不设置order或者设置相同的order, GridCol按照代码顺序展示。GridCol排序是按order从小到大的排列。未设置order的GridCol依次排序靠前,设置了order的GridCol按照数值从小到大排列。
当类型为number时。例如:order: 2,表示序号为2
当类型为GridColColumnOption时,例如:offset: { xs: 1, sm: 2, md: 3, lg: 4 },逻辑与span类型,分断点情况设置的序号
示例代码和效果图如下:
@Entry
@Component
struct Index {
colors: Color[] = [
Color.Red, Color.Yellow, Color.Pink, Color.Orange,
Color.Brown, Color.Blue, Color.Yellow, Color.Orange,
Color.Gray, Color.Pink, Color.Orange, Color.Brown];
build() {
Column({ space: 30 }) {
GridRow({
columns: 10 // 表示一共把GridRow的宽度分为10列
}) {
ForEach(this.colors, (item: Color, index: Number) => {
GridCol({
span: 2 // 共10份,此设置表示占2份的宽度, 所以会展示5列
}) {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}.width('100%').height(50)
}
.backgroundColor(item)
}, (item: Color) => item.toString())
}
.width('100%')
.height(500)
.backgroundColor('#f5f5f5')
GridRow({
columns: 10 // 10列
}) {
ForEach(this.colors, (item: Color, index: number) => {
GridCol({
span: 2,
offset: 2 // 子组件偏移相同列数2,当一行的最后偏移量不够时,需要换行继续偏移
// offset: {xs: 2, sm: 3} // 与span属性类似,也支持分断点传值
}) {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}
.backgroundColor(item)
.width('100%')
.height(50)
}
}, (item: Color) => item.toString())
}
.width('100%')
.height(500)
.backgroundColor('#f5f5f5')
GridRow({ columns: 12 }) {
ForEach(this.colors, (item: Color, index: number) => {
GridCol({
span: 2,
order: 12 - index // 与文案相反排列
// order: { xs: 1, sm: 2, md: 3, lg: 4 } //与span属性类似,也支持分断点传值
}) {
Row() {
Text(index.toString())
.fontSize(20)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
}
.backgroundColor(item)
.width('100%')
.height(50)
}
}, (item: Color) => item.toString())
}
}
.width('100%')
}
}