文章目录
一、布局简介
自适应布局是通过设定元素与外部容器的相对关系实现的。当外部容器大小、位置等发生变化时,元素即可以根据相对关系自动变化以适应外部环境的变化。通常自适应布局能根据vp/px变化进行无级连续的变化。
- 自适应布局常常需要借助Row组件、Column组件或Flex组件实现。
- 针对常见的开发场景,方舟开发框架提炼了七种自适应布局能力,这些布局可以独立使用,也可多种布局叠加使用。
自适应布局能力 | 使用场景 | 实现方式 |
---|---|---|
拉伸能力 | 容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。 | Flex布局的flexGrow和flexShrink属性 |
均分能力 | 容器组件尺寸发生变化时,增加或减小的空间均匀分配给容器组件内所有空白区域。 | Row组件、Column组件或Flex组件的justifyContent属性设置为FlexAlign.SpaceEvenly |
占比能力 | 子组件的宽或高按照预设的比例,随容器组件发生变化。 | 基于通用属性的两种实现方式: 将子组件的宽高设置为父组件宽高的百分比 layoutWeight属性 |
缩放能力 | 子组件的宽高按照预设的比例,随容器组件发生变化,且变化过程中子组件的宽高比不变。 | 布局约束的aspectRatio属性 |
延伸能力 | 容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。 | 基于容器组件的两种实现方式: 通过List组件实现 通过Scroll组件配合Row组件或Column组件实现 |
隐藏能力 | 容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏。相同显示优先级的子组件同时显示或隐藏。 | 布局约束的displayPriority属性 |
折行能力 | 容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,自动换行。 | Flex组件的wrap属性设置为FlexWrap.Wrap |
二、自适应拉伸
某单个内容或某组内容的显示宽度不是固定值,而是通过相对参照物的方式来确定其显示宽度。当参照物的宽度发生变化时,内容或内容间距的宽度随之发生自适应拉伸。
自适应拉伸适用于文字、普通按钮、间距等展示宽度灵活,对宽高比不敏感的内容和内容组合。
当可能出现的拉伸宽度不足以显示默认内容时,应根据场景选择优先保证内容完整或者优先保证其他内容的屏效,并进行截断或换行等组合适配。
1、左右拉伸
例如,列表开关组合中,在窗口宽度变化时,开关控件固定宽度并相对列表的右边缘位置固定,整个组合与文本宽度均自适应变化。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
build() {
Column() {
Row() {
Text('健康使用手机')
.fontSize(16)
.height(22)
.fontWeight(FontWeight.Medium)
.lineHeight(22)
Blank() // 通过Blank组件实现拉伸能力
Toggle({ type: ToggleType.Switch })
.width(36)
.height(20)
}
.height(55)
.borderRadius(12)
.padding({ left: 15, right: 15 })
.backgroundColor('#FFFFFF')
.width('100%')//此处宽度变化时,文字和开关的尺寸固定,仅有中间空白区域(Blank组件)随父容器尺寸变化而伸缩。
}
.height('100%')
.width('100%')
.padding(20)
.backgroundColor(Color.Gray)
}
}
2、均分拉伸
例如,在图标型网格中,当窗口宽度变化时,入口图标间距与图标离左右边缘间距同时均等变化。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
readonly list: number [] = [0, 1, 2, 3]
build() {
Column() {
// 均匀分配父容器主轴方向的剩余空间
Row() {
ForEach(this.list, (item: number) => {
Column() {
Image($r("app.media.startIcon"))
.width(48)
.height(48)
.margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}
.width(80)
.height(102)
.flexShrink(1)
})
}
.width('100%')//宽度变化时,图标及文字的尺寸不变,图标间的间距及图标离左右边缘的距离同时均等改变。
.justifyContent(FlexAlign.SpaceEvenly)
}
.height('100%')
.width('100%')
.backgroundColor(Color.White)
}
}
三、自适应缩放
组件的显示大小是固定比例,通过相对参照物的方式来确定其宽或高。当参照物的大小发生变化时,元素的大小随之发生自适应缩放。
自适应缩放适用于图片、圆形按钮、banner、反应真实物体形状的图像等必须保证宽高比的内容。
不推荐将所有元素同时缩放、或某内容放大过大超过屏幕50%。这将导致获取信息量不增反减,不符合用户预期。
1、完整缩放
例如,在宽度或高度变化时,时钟始终保证表盘完整展示并根据较短边决定宽高。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
build() {
Column() {
Column() {
Column() {
Image($r("app.media.1"))
.width('100%')
.height('100%')
}
.aspectRatio(1)// 固定宽高比
}
.backgroundColor(Color.Pink)
.height(200)//这里宽或高改变是,图片也随之变化
.width(400)//这里宽或高改变是,图片也随之变化
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
.height('100%')
.width('100%')
.backgroundColor(Color.White)
}
}
2、占比缩放
例如,带主体和背景的插画,画面内容根据宽度变化裁切,根据高度变化按50%比例缩放。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
build() {
Column() {
Row(){
}
.backgroundImage($r('app.media.banner'))
.backgroundImageSize(ImageSize.Cover)
.width('100%')
.layoutWeight(1)
Row(){
}
.backgroundColor(Color.White)
.width('100%')
.layoutWeight(1)
}
.height('100%')
.width('100%')
.backgroundColor(Color.Gray)
}
}
四、自适应延伸
组件的显示数量不是固定的,而是通过相对参照物的方式来确定其显示数量。当参照物的宽度发生变化时,组件随之发生自适应延伸显示更多数量。
自适应延伸/隐藏适用于页签、操作块、推荐栏目等具有相同交互层级且有更多数据可以填充的内容。
注意:需要判断因隐藏而不展示的内容对功能完整性是否有影响,并考虑通过滑动或“更多”按钮提供查看使用该内容的方式。
1、同功能内容延伸
例如,子页签和可滑动宫格在默认宽度下通过露出最后内容,提示右方有更多入口,在宽度变化时,可在每个元素宽度不变、保持滑动交互时显示更多数量。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
readonly appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7]
build() {
Column() {
Row({ space: 10 }) {
// 通过List组件实现隐藏能力
List({ space: 10 }) {
ForEach(this.appList, (item:number) => {
ListItem() {
Column() {
Image($r("app.media.startIcon"))
.width(48)
.height(48)
.margin({ top: 8 })
Text('App name')
.width(64)
.height(30)
.lineHeight(15)
.fontSize(12)
.textAlign(TextAlign.Center)
.margin({ top: 8 })
.padding({ bottom: 15 })
}.width(80).height(102)
}.width(80).height(102)
})
}
.padding({ top: 16, left: 10 })
.listDirection(Axis.Horizontal)
.width('100%')
.height(118)
.borderRadius(16)
.backgroundColor(Color.White)
}
.width('100%')//这里宽度变化,页面中显示的图标数量随之发生改变。
}
.height('100%')
.width('100%')
.backgroundColor(Color.Gray)
}
}
2、不同功能内容延伸或隐藏
例如,默认处于同一排的不同音乐播放按钮优先级不同,在宽度变化时可延伸或隐藏低优先级的按钮,最大化适应不同窗口尺寸。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
build() {
Column() {
Row({ space:24 }) {
Image($r("sys.media.ohos_ic_public_sound_off"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.displayPriority(1) // 布局优先级
Image($r("sys.media.ohos_ic_public_play_last"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.displayPriority(2) // 布局优先级
Image($r("sys.media.ohos_ic_public_pause"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.displayPriority(3) // 布局优先级
Image($r("sys.media.ohos_ic_public_play_next"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.displayPriority(2) // 布局优先级
Image($r("sys.media.ohos_ic_public_more"))
.width(48)
.height(48)
.objectFit(ImageFit.Contain)
.displayPriority(1) // 布局优先级
}
.width('100%')//父容器宽度发生变化时,其子元素按照预设的优先级显示或隐藏。
.height(96)
.borderRadius(16)
.backgroundColor('#FFFFFF')
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
}
.height('100%')
.width('100%')
.padding(10)
.backgroundColor(Color.Gray)
}
}
五、自适应折行
定义了折行能力的组件,可以根据组件容器的可用空间,体现纵向布局或者横向布局。
自适应折行适用于页签、操作块、内容流等具有相同交互层级,且希望保证类型和数量完整性的内容。
自适应布局对应OpenHarmony系统提供的自适应布局能力中的拉伸、均分、缩放、占比、延伸、隐藏、折行。
例如,在宽度足够时,操作块位于同一行,在宽度变小时,可根据内容能显示的宽度纵向排布。
示例代码
@Entry
@Component
struct AdaptiveLayoutPage {
readonly searchList: string [] = ['摇滚', '九十年代金曲', '交响乐', '流行']
build() {
Column() {
// 通过Flex组件warp参数实现自适应折行
Flex({
direction: FlexDirection.Row,
alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Start,
wrap: FlexWrap.Wrap
}) {
ForEach(this.searchList, (item: Resource) => {
Text(item)
.padding({
top: 8,
bottom: 8,
left: 20,
right: 20
})
.margin(8)
.fontSize(16)
.fontWeight(500)
.borderRadius('50%')
.backgroundColor('#e1e3e5')
})
}
.backgroundColor('#FFFFFF')
.padding(10)
.width('100%')//当父容器宽度发生变化,其中的内容做自适应换行。
.borderRadius(15)
}
.height('100%')
.width('100%')
.padding(10)
.backgroundColor(Color.Gray)
}
}
点击下方按钮添加微信,领取相关资料、学习方案。一键三连+关注,你的支持是我创作的动力。在这里,我乐于倾囊相授。
标签:鸿蒙,width,100%,示例,height,适应,HarmonyOS,宽度,组件 From: https://blog.csdn.net/shanghai597/article/details/145009531