1# 自适应布局 2 3 4针对常见的开发场景,方舟开发框架提炼了七种自适应布局能力,这些布局可以独立使用,也可多种布局叠加使用。 5 6 7 | 自适应布局类别 | 自适应布局能力 | 使用场景 | 实现方式 | 8| -------- | -------- | -------- | -------- | 9| 自适应拉伸 | [拉伸能力](#拉伸能力) | 容器组件尺寸发生变化时,增加或减小的空间**全部分配**给容器组件内**指定区域**。 | [Flex布局](../../reference/arkui-ts/ts-universal-attributes-flex-layout.md)的flexGrow和flexShrink属性 | 10| | [均分能力](#均分能力) | 容器组件尺寸发生变化时,增加或减小的空间**均匀分配**给容器组件内**所有空白区域**。 | [Row组件](../../reference/arkui-ts/ts-container-row.md)、[Column组件](../../reference/arkui-ts/ts-container-column.md)或[Flex组件](../../reference/arkui-ts/ts-container-flex.md)的justifyContent属性设置为FlexAlign.SpaceEvenly | 11| 自适应缩放 | [占比能力](#占比能力) | 子组件的宽或高**按照预设的比例**,随容器组件发生变化。 | 基于通用属性的两种实现方式:<br/>- 将子组件的宽高设置为父组件宽高的百分比<br/>- layoutWeight属性 | 12| | [缩放能力](#缩放能力) | 子组件的宽高**按照预设的比例**,随容器组件发生变化,且变化过程中子组件的**宽高比不变**。 | [布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md)的aspectRatio属性 | 13| 自适应延伸 | [延伸能力](#延伸能力) | 容器组件内的子组件,按照其**在列表中的先后顺序**,随容器组件尺寸变化显示或隐藏。 | 基于容器组件的两种实现方式:<br/>- 通过[List组件](../../reference/arkui-ts/ts-container-list.md)实现<br/>- 通过[Scroll组件](../../reference/arkui-ts/ts-container-scroll.md)配合[Row组件](../../reference/arkui-ts/ts-container-row.md)或[Column组件](../../reference/arkui-ts/ts-container-column.md)实现 | 14| | [隐藏能力](#隐藏能力) | 容器组件内的子组件,按照其**预设的显示优先级**,随容器组件尺寸变化显示或隐藏。**相同显示优先级的子组件同时显示或隐藏**。 | [布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md)的displayPriority属性 | 15| 自适应折行 | [折行能力](#折行能力) | 容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,**自动换行**。 | [Flex组件](../../reference/arkui-ts/ts-container-flex.md)的wrap属性设置为FlexWrap.Wrap | 16 17 18下面我们依次介绍这几种自适应布局能力。 19 20 21## 拉伸能力 22 23 24拉伸能力是指容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。 25 26 27拉伸能力通常通过[Flex布局](../../reference/arkui-ts/ts-universal-attributes-flex-layout.md)中的flexGrow和flexShrink属性实现,flexGrow和flexShink属性常与flexBasis属性搭配使用,故将这三个属性放在一起介绍。 28 29 30 | 属性 | 类型 | 默认值 | 描述 | 31| -------- | -------- | -------- | -------- | 32| flexGrow | number | 0 | 仅当父容器宽度大于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例拉伸,分配父容器的多余空间。 | 33| flexShrink | number | 1 | 仅当父容器宽度小于所有子组件宽度的总和时,该属性生效。配置了此属性的子组件,按照比例收缩,分配父容器的不足空间。 | 34| flexBasis | 'auto' \| [Length](../../reference/arkui-ts/ts-types.md#length) | 'auto' | 设置组件在Flex容器中主轴方向上基准尺寸。'auto'意味着使用组件原始的尺寸,不做修改。<br/>flexBasis属性不是必须的,通过width或height也可以达到同样的效果。当flexBasis属性与width或height发生冲突时,以flexBasis属性为准。 | 35 36 37> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 38> - 开发者期望将父容器的剩余空间全部分配给某空白区域时,也可以通过[Blank组件](../../reference/arkui-ts/ts-basic-components-blank.md)实现。注意仅当父组件为Row\Column\Flex组件时,Blank组件才会生效。 39> 40> - 类Web开发范式也是通过flex-grow和flex-shrink实现拉伸能力,同时也支持配置flex-basis,详见[通用样式](../../reference/arkui-js/js-components-common-styles.md)。 41> 42> - 类Web开发范式没有提供blank组件,但可以通过div组件模拟blank组件的行为,如“<div style='flex-grow: 1; flex-shrink: 0; flex-basis: 0'></div>”。 43 44**示例1** 45 46 47本示例中的页面由中间的内容区(包含一张图片)以及两侧的留白区组成,各区域的属性配置如下。 48 49* 中间内容区的宽度设置为400vp,同时将flexGrow属性设置为1,flexShrink属性设置为0。 50 51* 两侧留白区的宽度设置为150vp,同时将flexGrow属性设置为0,flexShrink属性设置为1。 52 53由上可知,父容器的基准尺寸是700vp(150vp+400vp+150vp)。 54 55可以通过拖动底部的滑动条改变父容器的尺寸,查看布局变化。 56 57* 当父容器的尺寸大于700vp时,父容器中多余的空间全部分配给中间内容区。 58 59* 当父容器的尺寸小于700vp时,左右两侧的留白区按照“1:1”的比例收缩(即平均分配父容器的不足空间)。 60 61 62![zh-cn_image_0000001335796258](figures/zh-cn_image_0000001335796258.gif) 63 64 65 66``` 67@Entry 68@Component 69struct FlexibleCapabilitySample1 { 70 @State containerWidth: number = 402 71 72 // 底部滑块,可以通过拖拽滑块改变容器尺寸。 73 @Builder slider() { 74 Slider({ value: this.containerWidth, min: 402, max: 1000, style: SliderStyle.OutSet }) 75 .blockColor(Color.White) 76 .width('60%') 77 .onChange((value: number) => { 78 this.containerWidth = value; 79 }) 80 .position({ x: '20%', y: '80%' }) 81 } 82 83 build() { 84 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, 85 alignItems: ItemAlign.Center }) { 86 Column() { 87 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, 88 alignItems: ItemAlign.Center }) { 89 // 通过flexGrow和flexShink属性,将多余的空间全部分配给图片,将不足的控件全部分配给两侧空白区域。 90 Row().width(150).height(400).backgroundColor('#FFFFFF') 91 .flexGrow(0).flexShrink(1) 92 Image($r("app.media.illustrator")).width(400).height(400) 93 .objectFit(ImageFit.Contain) 94 .backgroundColor("#66F1CCB8") 95 .flexGrow(1).flexShrink(0) 96 Row().width(150).height(400).backgroundColor('#FFFFFF') 97 .flexGrow(0).flexShrink(1) 98 }.width(this.containerWidth) 99 } 100 101 this.slider() 102 }.width('100%').height('100%').backgroundColor('#F1F3F5') 103 } 104} 105``` 106 107**示例2** 108 109 110文字和开关的尺寸固定,仅有中间空白区域(Blank组件)随父容器尺寸变化而伸缩。 111 112 113![zh-cn_image_0000001335316714](figures/zh-cn_image_0000001335316714.gif) 114 115 116 117``` 118@Entry 119@Component 120struct FlexibleCapabilitySample2 { 121 @State rate: number = 0.8 122 123 // 底部滑块,可以通过拖拽滑块改变容器尺寸 124 @Builder slider() { 125 Slider({ value: this.rate * 100, min: 30, max: 80, style: SliderStyle.OutSet }) 126 .blockColor(Color.White) 127 .width('60%') 128 .onChange((value: number) => { 129 this.rate = value / 100; 130 }) 131 .position({ x: '20%', y: '80%' }) 132 } 133 134 build() { 135 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, 136 alignItems: ItemAlign.Center }) { 137 Column() { 138 Row() { 139 Text('飞行模式') 140 .fontSize(16) 141 .width(135) 142 .height(22) 143 .fontWeight(FontWeight.Medium) 144 .lineHeight(22) 145 Blank() // 通过Blank组件实现拉伸能力 146 Toggle({ type: ToggleType.Switch }) 147 .width(36) 148 .height(20) 149 } 150 .height(55) 151 .borderRadius(12) 152 .padding({ left: 13, right: 13 }) 153 .backgroundColor('#FFFFFF') 154 .width(this.rate * 100 + '%') 155 } 156 157 this.slider() 158 }.width('100%').height('100%').backgroundColor('#F1F3F5') 159 } 160} 161``` 162 163 164## 均分能力 165 166 167均分能力是指容器组件尺寸发生变化时,增加或减小的空间均匀分配给容器组件内所有空白区域。它常用于内容数量固定、均分显示的场景,比如工具栏、底部菜单栏等。 168 169 170均分能力可以通过将[Row组件](../../reference/arkui-ts/ts-container-row.md)、[Column组件](../../reference/arkui-ts/ts-container-column.md)或[Flex组件](../../reference/arkui-ts/ts-container-flex.md)的justifyContent属性设置为FlexAlign.SpaceEvenly实现,即子元素在父容器主轴方向等间距布局,相邻元素之间的间距、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样。 171 172 173> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 174> - 均分能力还可以通过其它方式实现,如使用[Grid网格组件](../../reference/arkui-ts/ts-container-grid.md)或在每个组件间添加Blank组件等。 175> 176> - 类Web开发范式中,通过将[div组件](../../reference/arkui-js/js-components-container-div.md)的justify-content属性设置为space-evenly来实现均分布局。 177 178 179**示例:** 180 181 182父容器尺寸变化过程中,图标及文字的尺寸不变,图标间的间距及图标离左右边缘的距离同时均等改变。 183 184 185![zh-cn_image_0000001335477142](figures/zh-cn_image_0000001335477142.gif) 186 187 188 189``` 190@Entry 191@Component 192struct EquipartitionCapabilitySample { 193 const list: number [] = [0, 1, 2, 3] 194 @State rate: number = 0.6 195 196 // 底部滑块,可以通过拖拽滑块改变容器尺寸 197 @Builder slider() { 198 Slider({ value: this.rate * 100, min: 30, max: 60, style: SliderStyle.OutSet }) 199 .blockColor(Color.White) 200 .width('60%') 201 .onChange((value: number) => { 202 this.rate = value / 100 203 }) 204 .position({ x: '20%', y: '80%' }) 205 } 206 207 build() { 208 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 209 Column() { 210 // 均匀分配父容器主轴方向的剩余空间 211 Flex({ justifyContent: FlexAlign.SpaceEvenly }) { 212 ForEach(this.list, (item) => { 213 Column() { 214 Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 }) 215 Text('App name') 216 .width(64) 217 .height(30) 218 .lineHeight(15) 219 .fontSize(12) 220 .textAlign(TextAlign.Center) 221 .margin({ top: 8 }) 222 .padding({ bottom: 15 }) 223 }.width(80).height(102) 224 }) 225 } 226 // 均匀分配父容器主轴方向的剩余空间 227 Flex({ justifyContent: FlexAlign.SpaceEvenly }) { 228 ForEach(this.list, (item) => { 229 Column() { 230 Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 }) 231 Text('App name') 232 .width(64) 233 .height(30) 234 .lineHeight(15) 235 .fontSize(12) 236 .textAlign(TextAlign.Center) 237 .margin({ top: 8 }) 238 .padding({ bottom: 15 }) 239 }.width(80).height(102) 240 }) 241 } 242 } 243 .width(this.rate * 100 + '%') 244 .height(222) 245 .padding({ top: 16 }) 246 .backgroundColor('#FFFFFF') 247 .borderRadius(16) 248 249 this.slider() 250 } 251 .width('100%') 252 .height('100%') 253 .backgroundColor('#F1F3F5') 254 } 255} 256``` 257 258 259## 占比能力 260 261 262占比能力是指子组件的宽高按照预设的比例,随父容器组件发生变化。 263 264 265占比能力通常有两种实现方式: 266 267 268- 将子组件的宽高设置为父组件宽高的百分比,详见[尺寸设置](../../reference/arkui-ts/ts-universal-attributes-size.md)及[长度类型](../../reference/arkui-ts/ts-types.md#length)。 269 270- 通过layoutWeight属性配置互为兄弟关系的组件在父容器主轴方向的布局权重,详见[尺寸设置](../../reference/arkui-ts/ts-universal-attributes-size.md)。 271 - 当父容器尺寸确定时,其子组件按照开发者配置的权重比例分配父容器中主轴方向的空间。 272 - 仅当父容器是Row、Colomn或者Flex时,layoutWeight属性才会生效。 273 - 设置layoutWeight属性后,组件本身的尺寸会失效。比如同时设置了.width('40%')和.layoutWeight(1),那么只有.layoutWeight(1)会生效。 274 275 276layoutWeight存在使用限制,所以实际使用过程中大多通过将子组件宽高设置为父组件的百分比来实现占比能力。 277 278 279> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 280> - 占比能力在实际开发中使用的非常广泛,可以通过很多不同的方式实现占比能力,如还可以通过[Grid组件](../../reference/arkui-ts/ts-container-grid.md)的columnsTemplate属性设置网格容器中列的数量及其宽度比例,或通过配置子组件在栅格(本章后文将详细介绍栅格系统)中占据不同的列数来实现占比能力。本小节仅介绍最基础和常用的实现方式,局限性较大或比非常小众的实现方式,本文不做展开介绍。 281> 282> - 类Web开发范式同样支持以百分比的形式设置组件的宽高,详见[通用样式](../../reference/arkui-js/js-components-common-styles.md)中关于width和height的介绍以及[长度类型介绍](../../reference/arkui-js/js-appendix-types.md#长度类型)。 283> 284> - 与声明式开发范式中的layoutWeight属性类似,类Web开发范式提供了[flex-weight样式](../../reference/arkui-js/js-components-common-atomic-layout.md#占比能力)用于配置互为兄弟关系的组件在父容器主轴方向的布局权重。 285 286 287**示例:** 288 289 290简单的播放控制栏,其中“上一首”、“播放/暂停”、“下一首”的layoutWeight属性都设置为1,因此它们按照“1:1:1”的比例均分父容器主轴方向的空间。 291 292 293将三个按钮的.layoutWeight(1)分别替换为.width('33%')、.width('34%')、.width('33%'),也可以实现与当前同样的显示效果。 294 295 296![zh-cn_image_0000001385757965](figures/zh-cn_image_0000001385757965.gif) 297 298 299 300``` 301@Entry 302@Component 303struct ProportionCapabilitySample { 304 @State rate: number = 0.5 305 306 // 底部滑块,可以通过拖拽滑块改变容器尺寸 307 @Builder slider() { 308 Slider({ value: 100, min: 25, max: 50, style: SliderStyle.OutSet }) 309 .blockColor(Color.White) 310 .width('60%') 311 .height(50) 312 .onChange((value: number) => { 313 this.rate = value / 100 314 }) 315 .position({ x: '20%', y: '80%' }) 316 } 317 318 build() { 319 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 320 Column() { 321 Row() { 322 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 323 Image($r("app.media.down")) 324 .width(48) 325 .height(48) 326 } 327 .height(96) 328 .layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重 329 330 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 331 Image($r("app.media.pause")) 332 .width(48) 333 .height(48) 334 } 335 .height(96) 336 .layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重 337 .backgroundColor('#66F1CCB8') 338 339 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 340 Image($r("app.media.next")) 341 .width(48) 342 .height(48) 343 } 344 .height(96) 345 .layoutWeight(1) // 设置子组件在父容器主轴方向的布局权重 346 } 347 .width(this.rate * 100 + '%') 348 .height(96) 349 .borderRadius(16) 350 .backgroundColor('#FFFFFF') 351 } 352 353 this.slider() 354 } 355 .width('100%') 356 .height('100%') 357 .backgroundColor('#F1F3F5') 358 } 359} 360``` 361 362 363 364## 缩放能力 365 366 367缩放能力是指子组件的宽高按照预设的比例,随容器组件发生变化,且变化过程中子组件的宽高比不变。 368 369 370缩放能力通过使用百分比布局配合**固定宽高比**(aspectRatio属性)实现当容器尺寸发生变化时,内容自适应调整。 371 372 373可以访问[布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md),了解aspectRatio属性的详细信息。 374 375 376> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 377> 类Web开发范式同样提供了[aspect-ratio样式](../../reference/arkui-js/js-components-common-atomic-layout.md#固定比例),用于固定组件的宽高比。 378 379 380**示例:** 381 382 383为方便查看效果,示例中特意给Column组件加了边框。可以看到Column组件随着其Flex父组件尺寸变化而缩放的过程中,始终保持预设的宽高比,其中的图片也始终正常显示。 384 385 386![zh-cn_image_0000001335640862](figures/zh-cn_image_0000001335640862.gif) 387 388 389 390``` 391@Entry 392@Component 393struct ScaleCapabilitySample { 394 @State sliderWidth: number = 400 395 @State sliderHeight: number = 400 396 397 // 底部滑块,可以通过拖拽滑块改变容器尺寸 398 @Builder slider() { 399 Slider({ value: this.sliderWidth, min: 100, max: 400, style: SliderStyle.OutSet }) 400 .blockColor(Color.White) 401 .width('60%') 402 .height(50) 403 .onChange((value: number) => { 404 this.sliderWidth = value; 405 }) 406 .position({ x: '20%', y: '80%' }) 407 Slider({ value: this.sliderHeight, min: 100, max: 400, style: SliderStyle.OutSet }) 408 .blockColor(Color.White) 409 .width('60%') 410 .height(50) 411 .onChange((value: number) => { 412 this.sliderHeight = value 413 }) 414 .position({ x: '20%', y: '87%' }) 415 } 416 417 build() { 418 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 419 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 420 Column() { 421 Image($r("app.media.illustrator")).width('100%').height('100%') 422 } 423 .aspectRatio(1) // 固定宽高比 424 .border({ width: 2, color: "#66F1CCB8"}) // 边框,仅用于展示效果 425 } 426 .backgroundColor("#FFFFFF") 427 .height(this.sliderWidth) 428 .width(this.sliderHeight) 429 430 this.slider() 431 }.width('100%') 432 .height('100%') 433 .backgroundColor("#F1F3F5") 434 } 435} 436``` 437 438 439## 延伸能力 440 441 442延伸能力是指容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。它可以根据显示区域的尺寸,显示不同数量的元素。 443 444 445延伸能力通常有两种实现方式: 446 447 448- 通过[List组件](../../reference/arkui-ts/ts-container-list.md)实现。 449 450- 通过[Scroll组件](../../reference/arkui-ts/ts-container-scroll.md)配合[Row组件](../../reference/arkui-ts/ts-container-row.md)或[Column组件](../../reference/arkui-ts/ts-container-column.md)实现。 451 452 453> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 454> - List、Row或Column组件中子节点的在页面显示时就已经全部完成了布局计算及渲染,只不过受限于父容器尺寸,用户只能看到一部分。随着父容器尺寸增大,用户可以看到的子节点数目也相应的增加。用户还可以通过手指滑动触发列表滑动,查看被隐藏的子节点。 455> 456> - 类Web开发范式同样可以使用[list组件](../../reference/arkui-js/js-components-container-list.md)实现延伸能力。 457> 458> - 类Web开发范式没有提供scroll组件,但可以将[div组件](../../reference/arkui-js/js-components-container-div.md)的overflow样式设置为scroll(即div组件主轴方向上子元素的尺寸超过div组件本身的尺寸时进行滚动显示)来模拟scroll组件的行为。 459 460 461**示例:** 462 463 464当父容器的尺寸发生改变时,页面中显示的图标数量随之发生改变。 465 466 467分别通过List组件实现及通过Scroll组件配合Row组件实现。 468 469 470![zh-cn_image_0000001335641246](figures/zh-cn_image_0000001335641246.gif) 471 472 473(1)通过List组件实现。 474 475 476 477``` 478@Entry 479@Component 480struct ExtensionCapabilitySample1 { 481 @State rate: number = 0.60 482 const appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7] 483 484 // 底部滑块,可以通过拖拽滑块改变容器尺寸 485 @Builder slider() { 486 Slider({ value: this.rate * 100, min: 8, max: 60, style: SliderStyle.OutSet }) 487 .blockColor(Color.White) 488 .width('60%') 489 .height(50) 490 .onChange((value: number) => { 491 this.rate = value / 100 492 }) 493 .position({ x: '20%', y: '80%' }) 494 } 495 496 build() { 497 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 498 Row({ space: 10 }) { 499 // 通过List组件实现隐藏能力 500 List({ space: 10 }) { 501 ForEach(this.appList, (item) => { 502 ListItem() { 503 Column() { 504 Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 }) 505 Text('App name') 506 .width(64) 507 .height(30) 508 .lineHeight(15) 509 .fontSize(12) 510 .textAlign(TextAlign.Center) 511 .margin({ top: 8 }) 512 .padding({ bottom: 15 }) 513 }.width(80).height(102) 514 }.width(80).height(102) 515 }) 516 } 517 .padding({ top: 16, left: 10 }) 518 .listDirection(Axis.Horizontal) 519 .width('100%') 520 .height(118) 521 .borderRadius(16) 522 .backgroundColor(Color.White) 523 } 524 .width(this.rate * 100 + '%') 525 526 this.slider() 527 } 528 .width('100%') 529 .height('100%') 530 .backgroundColor('#F1F3F5') 531 } 532} 533``` 534 535 536 (2)通过Scroll组件配合Row组件实现。 537 538``` 539@Entry 540@Component 541struct ExtensionCapabilitySample2 { 542 private scroller: Scroller = new Scroller() 543 @State rate: number = 0.60 544 @State appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7] 545 546 // 底部滑块,可以通过拖拽滑块改变容器尺寸 547 @Builder slider() { 548 Slider({ value: this.rate * 100, min: 8, max: 60, style: SliderStyle.OutSet }) 549 .blockColor(Color.White) 550 .width('60%') 551 .height(50) 552 .onChange((value: number) => { 553 this.rate = value / 100; 554 }) 555 .position({ x: '20%', y: '80%' }) 556 } 557 558 build() { 559 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 560 // 通过Scroll和Row组件实现隐藏能力 561 Scroll(this.scroller) { 562 Row({ space: 10 }) { 563 ForEach(this.appList, () => { 564 Column() { 565 Image($r("app.media.icon")).width(48).height(48).margin({ top: 8 }) 566 Text('App name') 567 .width(64) 568 .height(30) 569 .lineHeight(15) 570 .fontSize(12) 571 .textAlign(TextAlign.Center) 572 .margin({ top: 8 }) 573 .padding({ bottom: 15 }) 574 575 576 }.width(80).height(102) 577 }) 578 } 579 .padding({ top: 16, left: 10 }) 580 .height(118) 581 .borderRadius(16) 582 .backgroundColor(Color.White) 583 } 584 .scrollable(ScrollDirection.Horizontal) 585 .width(this.rate * 100 + '%') 586 587 this.slider() 588 } 589 .width('100%') 590 .height('100%') 591 .backgroundColor('#F1F3F5') 592 } 593} 594``` 595 596 597 598## 隐藏能力 599 600隐藏能力是指容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏,其中相同显示优先级的子组件同时显示或隐藏。它是一种比较高级的布局方式,常用于分辨率变化较大,且不同分辨率下显示内容有所差异的场景。主要思想是通过增加或减少显示内容,来保持最佳的显示效果。 601 602隐藏能力通过设置**布局优先级**(displayPriority属性)来控制显隐,当布局主轴方向剩余尺寸不足以满足全部元素时,按照布局优先级大小,从小到大依次隐藏,直到容器能够完整显示剩余元素。具有相同布局优先级的元素将同时显示或者隐藏。 603 604可以访问[布局约束](../../reference/arkui-ts/ts-universal-attributes-layout-constraints.md),了解displayPriority属性的详细信息。 605 606> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 607> 类Web开发范式同样支持[display-index样式](../../reference/arkui-js/js-components-common-atomic-layout.md#隐藏能力),用于设置布局优先级。 608 609**示例:** 610 611父容器尺寸发生变化时,其子元素按照预设的优先级显示或隐藏。 612 613![zh-cn_image_0000001335485154](figures/zh-cn_image_0000001335485154.gif) 614 615 616``` 617@Entry 618@Component 619struct HiddenCapabilitySample { 620 @State rate: number = 0.45 621 622 // 底部滑块,可以通过拖拽滑块改变容器尺寸 623 @Builder slider() { 624 Slider({ value: this.rate * 100, min: 10, max: 45, style: SliderStyle.OutSet }) 625 .blockColor(Color.White) 626 .width('60%') 627 .height(50) 628 .onChange((value: number) => { 629 this.rate = value / 100 630 }) 631 .position({ x: '20%', y: '80%' }) 632 } 633 634 build() { 635 Flex({ direction: FlexDirection.Column, 636 justifyContent: FlexAlign.Center, 637 alignItems: ItemAlign.Center }) { 638 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 639 Image($r("app.media.favorite")) 640 .width(48) 641 .height(48) 642 .objectFit(ImageFit.Contain) 643 .margin({ left: 12, right: 12 }) 644 .displayPriority(1) // 布局优先级 645 646 Image($r("app.media.down")) 647 .width(48) 648 .height(48) 649 .objectFit(ImageFit.Contain) 650 .margin({ left: 12, right: 12 }) 651 .displayPriority(2) // 布局优先级 652 653 Image($r("app.media.pause")) 654 .width(48) 655 .height(48) 656 .objectFit(ImageFit.Contain) 657 .margin({ left: 12, right: 12 }) 658 .displayPriority(3) // 布局优先级 659 660 Image($r("app.media.next")) 661 .width(48) 662 .height(48) 663 .objectFit(ImageFit.Contain) 664 .margin({ left: 12, right: 12 }) 665 .displayPriority(2) // 布局优先级 666 667 Image($r("app.media.list")) 668 .width(48) 669 .height(48) 670 .objectFit(ImageFit.Contain) 671 .margin({ left: 12, right: 12 }) 672 .displayPriority(1) // 布局优先级 673 } 674 .width(this.rate * 100 + '%') 675 .height(96) 676 .borderRadius(16) 677 .backgroundColor('#FFFFFF') 678 679 this.slider() 680 } 681 .width('100%') 682 .height('100%') 683 .backgroundColor('#F1F3F5') 684 } 685} 686``` 687 688 689## 折行能力 690 691折行能力是指容器组件尺寸发生变化,当布局方向尺寸不足以显示完整内容时自动换行。它常用于横竖屏适配或默认设备向平板切换的场景。 692 693折行能力通过使用 **Flex折行布局** (将wrap属性设置为FlexWrap.Wrap)实现,当横向布局尺寸不足以完整显示内容元素时,通过折行的方式,将元素显示在下方。 694 695可以访问[Flex组件](../../reference/arkui-ts/ts-container-flex.md),了解Flex组件的详细用法。 696 697> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 698> 类Web开发范式通过将[div组件](../../reference/arkui-js/js-components-container-div.md)的flex-warp样式设置为wrap来使用折行能力。 699 700**示例:** 701 702父容器中的图片尺寸固定,当父容器尺寸发生变化,其中的内容做自适应换行。 703 704![zh-cn_image_0000001385645821](figures/zh-cn_image_0000001385645821.gif) 705 706 707``` 708@Entry 709@Component 710struct WrapCapabilitySample { 711 @State rate: number = 0.7 712 const imageList: Resource [] = [ 713 $r('app.media.flexWrap1'), 714 $r('app.media.flexWrap2'), 715 $r('app.media.flexWrap3'), 716 $r('app.media.flexWrap4'), 717 $r('app.media.flexWrap5'), 718 $r('app.media.flexWrap6') 719 ] 720 721 // 底部滑块,可以通过拖拽滑块改变容器尺寸 722 @Builder slider() { 723 Slider({ value: this.rate * 100, min: 50, max: 70, style: SliderStyle.OutSet }) 724 .blockColor(Color.White) 725 .width('60%') 726 .onChange((value: number) => { 727 this.rate = value / 100 728 }) 729 .position({ x: '20%', y: '87%' }) 730 } 731 732 build() { 733 Flex({ justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) { 734 Column() { 735 // 通过Flex组件warp参数实现自适应折行 736 Flex({ 737 direction: FlexDirection.Row, 738 alignItems: ItemAlign.Center, 739 justifyContent: FlexAlign.Center, 740 wrap: FlexWrap.Wrap 741 }) { 742 ForEach(this.imageList, (item) => { 743 Image(item).width(183).height(138).padding(10) 744 }) 745 } 746 .backgroundColor('#FFFFFF') 747 .padding(20) 748 .width(this.rate * 100 + '%') 749 .borderRadius(16) 750 } 751 .width('100%') 752 753 this.slider() 754 }.width('100%') 755 .height('100%') 756 .backgroundColor('#F1F3F5') 757 } 758} 759``` 760