相对布局
RelativeContainer支持容器内部的子元素设置相对位置关系,支持指定兄弟元素作为锚点,也支持指定父容器作为锚点,基于锚点做相对位置布局。
锚点设置
锚点设置是指设置子元素相对于父元素或者是兄弟元素的位置依赖关系,在水平方向上,可以设置left、middle、right的锚点。在竖直方向上,可以设置top、center、bottom的锚点。
为了明确定义锚点,必须为RelativeContainer及其子元素设置ID,用于指定锚点信息。
RelativeContainer的ID默认为_container_
,其余子元素的ID通过属性设置。
不设置id的组件不能被其他子组件作为锚点。
互相依赖,环形依赖时容器内子组件全部不绘制。
同方向两个以上位置被设置锚点,但锚点位置逆序时,此组件大小为0,即不绘制。
锚点设置通过alignRules
方法进行设置
@Entry
@Component
struct Index {
build() {
Row() {
RelativeContainer() {
Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100)
.backgroundColor('#ff3339ff')
.alignRules({
top: {anchor: "__container__", align: VerticalAlign.Top},
left: {anchor: "__container__", align: HorizontalAlign.Start}
})
.id("row1")
Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100)
.backgroundColor('#ff298e1e')
.alignRules({
top: {anchor: "__container__", align: VerticalAlign.Top},
right: {anchor: "__container__", align: HorizontalAlign.End},
bottom: {anchor: "row1", align: VerticalAlign.Center},
})
.id("row2")
Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100)
.backgroundColor('#ffff6a33')
.alignRules({
top: {anchor: "row1", align: VerticalAlign.Bottom},
left: {anchor: "row1", align: HorizontalAlign.Start},
right: {anchor: "row2", align: HorizontalAlign.Start}
})
.id("row3")
Row(){Text('row4')}.justifyContent(FlexAlign.Center)
.backgroundColor('#ffff33fd')
.alignRules({
top: {anchor: "row3", align: VerticalAlign.Bottom},
left: {anchor: "row1", align: HorizontalAlign.Center},
right: {anchor: "row2", align: HorizontalAlign.End},
bottom: {anchor: "__container__", align: VerticalAlign.Bottom}
})
.id("row4")
}
.width(300).height(300)
.margin({left: 50})
.border({width:2, color: "#6699FF"})
}
.height('100%')
}
}
位置偏移
在设置相对位置之后,还可以通过offset
来设置额外的偏移量。
@Entry
@Component
struct Index {
build() {
Row() {
RelativeContainer() {
Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100)
.backgroundColor("#FF3333")
.alignRules({
top: {anchor: "__container__", align: VerticalAlign.Top},
left: {anchor: "__container__", align: HorizontalAlign.Start}
})
.id("row1")
Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100)
.backgroundColor("#FFCC00")
.alignRules({
top: {anchor: "__container__", align: VerticalAlign.Top},
right: {anchor: "__container__", align: HorizontalAlign.End},
bottom: {anchor: "row1", align: VerticalAlign.Center},
})
.offset({
x:-40,
y:-20
})
.id("row2")
Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100)
.backgroundColor("#FF6633")
.alignRules({
top: {anchor: "row1", align: VerticalAlign.Bottom},
left: {anchor: "row1", align: HorizontalAlign.End},
right: {anchor: "row2", align: HorizontalAlign.Start}
})
.offset({
x:-10,
y:-20
})
.id("row3")
Row(){Text('row4')}.justifyContent(FlexAlign.Center)
.backgroundColor("#FF9966")
.alignRules({
top: {anchor: "row3", align: VerticalAlign.Bottom},
bottom: {anchor: "__container__", align: VerticalAlign.Bottom},
left: {anchor: "__container__", align: HorizontalAlign.Start},
right: {anchor: "row1", align: HorizontalAlign.End}
})
.offset({
x:-10,
y:-30
})
.id("row4")
Row(){Text('row5')}.justifyContent(FlexAlign.Center)
.backgroundColor("#FF66FF")
.alignRules({
top: {anchor: "row3", align: VerticalAlign.Bottom},
bottom: {anchor: "__container__", align: VerticalAlign.Bottom},
left: {anchor: "row2", align: HorizontalAlign.Start},
right: {anchor: "row2", align: HorizontalAlign.End}
})
.offset({
x:10,
y:20
})
.id("row5")
Row(){Text('row6')}.justifyContent(FlexAlign.Center)
.backgroundColor('#ff33ffb5')
.alignRules({
top: {anchor: "row3", align: VerticalAlign.Bottom},
bottom: {anchor: "row4", align: VerticalAlign.Bottom},
left: {anchor: "row3", align: HorizontalAlign.Start},
right: {anchor: "row3", align: HorizontalAlign.End}
})
.offset({
x:-15,
y:10
})
.backgroundImagePosition(Alignment.Bottom)
.backgroundImageSize(ImageSize.Cover)
.id("row6")
}
.width(300).height(300)
.margin({left: 50})
.border({width:2, color: "#6699FF"})
}
.height('100%')
}
}
栅格布局
栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用。主要优势包括:
-
提供可循的规律:栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题。通过将页面划分为等宽的列数和行数,可以方便地对页面元素进行定位和排版。
-
统一的定位标注:栅格布局可以为系统提供一种统一的定位标注,保证不同设备上各个模块的布局一致性。这可以减少设计和开发的复杂度,提高工作效率。
-
灵活的间距调整方法:栅格布局可以提供一种灵活的间距调整方法,满足特殊场景布局调整的需求。通过调整列与列之间和行与行之间的间距,可以控制整个页面的排版效果。
-
自动换行和自适应:栅格布局可以完成一对多布局的自动换行和自适应。当页面元素的数量超出了一行或一列的容量时,他们会自动换到下一行或下一列,并且在不同的设备上自适应排版,使得页面布局更加灵活和适应性强。
GridRow为栅格容器组件,需与栅格子组件GridCol在栅格布局场景中联合使用。
栅格容器GridRow
栅格系统断点
栅格系统以设备的水平宽度作为断点依据,定义设备的宽度类型,形成了一套断点规则。可以根据需求在不同的断点区间实现不同的页面布局效果。
栅格系统默认断点将设备宽度分为xs、sm、md、lg四类,尺寸范围如下:
断点名称 | 取值范围 | 设备描述 |
---|---|---|
xs | [0,320) | 最小宽度类 |
sm | [320,520) | 小宽度类 |
md | [520,840) | 中等宽度类 |
lg | [840,+∞) | 大宽度类 |
在GridRow中,允许使用breakpoints
参数自定义修改断点的取值范围,最多支持6个断点,除了默认的四个以外,还可以启用xl(特大宽度类型设备)、xxl(超大宽度类型设备)两个断点。
breakpoints: {value: ['320vp', '520vp', '840vp', '1080vp']}
表示启用xs、sm、md、lg、xl5个断点,小于320vp的为xs,320-520的为sm、520-840的为md、840-1080的为lg、1080以上的为xl。
栅格的默认列数是12列,通过断点设置将应用段度分为6个区间,在各个区间中,每个栅格子元素占用的列数均不同。
@State bgColors: Color[] = [Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Pink, Color.Grey, Color.Blue, Color.Brown];
...
GridRow({
breakpoints: {
value: ['200vp', '300vp', '400vp', '500vp', '600vp'],
reference: BreakpointsReference.WindowSize
}
}) {
ForEach(this.bgColors, (color:Color, index?:number|undefined) => {
GridCol({
span: {
xs: 2, // 在最小宽度类型设备上,栅格子组件占据的栅格容器2列。
sm: 3, // 在小宽度类型设备上,栅格子组件占据的栅格容器3列。
md: 4, // 在中等宽度类型设备上,栅格子组件占据的栅格容器4列。
lg: 6, // 在大宽度类型设备上,栅格子组件占据的栅格容器6列。
xl: 8, // 在特大宽度类型设备上,栅格子组件占据的栅格容器8列。
xxl: 12 // 在超大宽度类型设备上,栅格子组件占据的栅格容器12列。
}
}) {
Row() {
Text(`${index}`)
}.width("100%").height('50vp')
}.backgroundColor(color)
})
}
可以实现如下效果:
布局的总列数
GridRow中系统默认的columns是12,可以通过参数columns
修改默认的总列数。支持数字类型直接修改所有断点情况下的总列数,也可以传入GridRowColumnOption
修改指定断点下的列数。
GridRow({ columns: 4 })
GridRow({ columns: { sm: 4, md: 8 }, breakpoints: { value: ['200vp', '300vp', '400vp', '500vp', '600vp'] } })
如果只修改中间断点的栅格总列数,那么小尺寸的将继续使用系统默认的columns,即12,较大尺寸的则默认使用前一个尺寸的columns,即8。
排列方向
在GridRow中,可以通过参数direction
来指定子组件的排列方向。
GridRow({ direction: GridRowDirection.Row }){}//从左到右
GridRow({ direction: GridRowDirection.RowReverse }){}//从右到左
子组件间距
在GridRow中,可以通过参数gutter
设置子元素在水平和垂直方向的间距。
GridRow({ gutter: 10 }){}//相邻子元素间距为10
GridRow({ gutter: { x: 20, y: 50 } }){}//水平间距为20,垂直间距为50
子组件GridCol
GridRow的子组件为GridCol,可以通过参数或者属性方法两种方式,设置span(占用列数)、offset(偏移列数)、order(元素序号)的值。
- span,子组件占栅格布局的列数,决定了子组件的宽度,默认为1。当类型为number时,子组件在所有尺寸设备中占用的列数相同。当类型为FridColumnOption时,支持六中不同尺寸设备中子组件所占列数设置。
let Gspan:Record<string,number> = { 'xs': 1, 'sm': 2, 'md': 3, 'lg': 4 } GridCol({ span: 2 }){} GridCol({ span: { xs: 1, sm: 2, md: 3, lg: 4 } }){} GridCol(){}.span(2) GridCol(){}.span(Gspan)
- offset,子组件相对于前一个子组件的偏移列数,默认为0。当设置为1时,那么子组件前边将多出来一个空的columns,总共占据的格子,就是子组件本身的列数+1。
let Goffset:Record<string,number> = { 'xs': 1, 'sm': 2, 'md': 3, 'lg': 4 } GridCol({ offset: 2 }){} GridCol({ offset: { xs: 2, sm: 2, md: 2, lg: 2 } }){} GridCol(){}.offset(Goffset)
- order,决定子组件的排列次序,当子组件不设置order或者设置相同的order时,子组件按照代码顺序展示。当设置不同的order时,order小的在前,order大的在后。部分设置order,部分不设置时,未设置order的靠前,设置了order的靠后,设置了order的按照order数字从小到大排列。
let Gorder:Record<string,number> = { 'xs': 1, 'sm': 2, 'md': 3, 'lg': 4 } GridCol({ order: 2 }){} GridCol({ order: { xs: 1, sm: 2, md: 3, lg: 4 } }){} GridCol(){}.order(2) GridCol(){}.order(Gorder)