1、概 述
针对常见的开发场景,ArkUI开发框架提供了非常多的自适应布局能力,这些布局可以独立使用,也可多种布局叠加使用。本文针对ArkUI提供的拉伸能力做简单讨论。
拉伸能力是指容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。效果类似如下:
做过前端开发的朋友应该使用过Flex布局,这是一个非常常用的布局方式,类似的,ArkUI也提供了Flex布局,我们在ArkUI中,可以借助flexGrow和flexShrink属性可以方便地实现自适应拉伸能力。
2、Flex布局实现拉伸能力
拉伸能力通常通过Flex布局中的flexGrow和flexShrink属性实现,flexGrow和flexShrink属性常与flexBasis属性搭配使用,这三个属性介绍如下:
属性 | 类型 | 描述 |
flexGrow | number | 默认为:0 仅当父容器宽度大于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例拉伸,分配父容器的多余空间。 |
flexShrink | number | 默认为:1 仅当父容器宽度小于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例收缩,分配父容器的不足空间。 |
flexBasis | 'auto' | Length | 默认为:'auto' 设置组件在Flex容器中主轴方向上基准尺寸。 'auto'意味着使用组件原始的尺寸,不做修改。flexBasis属性不是必须的,通过width或height也可以达到同样的效果。当flexBasis属性与width或height发生冲突时,以flexBasis属性为准。 |
3、案 例
本示例中的页面由中间的内容区(包含一张图片)以及两侧的留白区组成,各区域的属性配置如下。
-
中间内容区的宽度设置为100vp,同时将flexGrow属性设置为1,flexShrink属性设置为0。
-
两侧留白区的宽度设置为100vp,同时将flexGrow属性设置为0,flexShrink属性设置为1。
由上可知,父容器的基准尺寸是300vp(100vp+100vp+100vp)。我们可以通过拖动底部的滑动条改变父容器的尺寸,查看布局变化。
-
当父容器的尺寸大于300vp时,父容器中多余的空间全部分配给中间内容区。
-
当父容器的尺寸小于300vp时,左右两侧的留白区按照“1:1”的比例收缩(即平均分配父容器的不足空间)。
效果如下:
代码如下(25、30、34行代码):
@Entry
@Component
struct FlexibleCapabilitySample1 {
@State containerWidth: number = 300
// 底部滑块,可以通过拖拽滑块改变容器尺寸。
@Builder slider() {
Slider({ value: this.containerWidth, min: 100, max: 1000, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.containerWidth = value;
})
.position({ x: '20%', y: '80%' })
}
build() {
Column() {
Text(`每列初始宽度:100 | 100 | 100`)
Text(`当前容器宽度:${this.containerWidth}`)
Column() {
Row() {
// 通过flexGrow和flexShrink属性,将多余的空间全部分配给图片,将不足的空间全部分配给两侧空白区域。
Row(){
Text('第一个区域')
}.width(100).height(100).backgroundColor(Color.Brown)
.flexGrow(0).flexShrink(1)
Image($r("app.media.background")).width(100).height(100)
.objectFit(ImageFit.Contain)
.backgroundColor(Color.Pink)
.border({width: 1, color: Color.Gray})
.flexGrow(1).flexShrink(0)
Row(){
Text('第二个区域')
}.width(100).height(100).backgroundColor(Color.Orange)
.flexGrow(0).flexShrink(1)
}
.width(this.containerWidth)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
}
this.slider()
}
.width('100%')
.height('100%')
.border({
width: 1,
color: Color.Gray
})
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
4、one more thing..
如果我们期望将父容器的剩余空间全部分配给某空白区域时,也可以通过Blank组件实现。
📢📢注意:
当仅当父组件为Row\Column\Flex组件时,Blank组件才会生效。
一个通过Blank实现拉伸效果的示例如下:
代码如下(27行代码):
@Entry
@Component
struct FlexibleCapabilitySample2 {
@State rate: number = 0.8
@State value: boolean = true;
// 底部滑块,可以通过拖拽滑块改变容器尺寸
@Builder slider() {
Slider({ value: this.rate * 100, min: 30, max: 80, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) => {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Column() {
Column() {
Text(`${this.value ? '已加入' : '待加入'}`)
Row() {
Text('Harmony自习室')
.fontSize(16)
.width(140)
.height(22)
.fontWeight(FontWeight.Medium)
.lineHeight(22)
Blank() // 通过Blank组件实现拉伸能力
Toggle({ type: ToggleType.Switch, isOn: $$this.value })
.width(36)
.height(20)
}
.height(55)
.borderRadius(12)
.padding({ left: 13, right: 13 })
.backgroundColor('#FFFFFF')
.width(this.rate * 100 + '%')
}
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}