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