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/>-&nbsp;将子组件的宽高设置为父组件宽高的百分比<br/>-&nbsp;layoutWeight属性 |
12|  | [缩放能力](#缩放能力) | 子组件的宽高**按照预设的比例**,随容器组件发生变化,且变化过程中子组件的**宽高比不变**。 | [布局约束](../../reference/apis-arkui/arkui-ts/ts-universal-attributes-layout-constraints.md)的aspectRatio属性 |
13| 自适应延伸 | [延伸能力](#延伸能力) | 容器组件内的子组件,按照其**在列表中的先后顺序**,随容器组件尺寸变化显示或隐藏。 | 基于容器组件的两种实现方式:<br/>-&nbsp;通过[List组件](../../reference/apis-arkui/arkui-ts/ts-container-list.md)实现<br/>-&nbsp;通过[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'&nbsp;\|&nbsp;[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组件的行为,如“&lt;div style='flex-grow: 1; flex-shrink: 0; flex-basis: 0'&gt;&lt;/div&gt;”。
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```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![zh-cn_image_0000001335316714](figures/zh-cn_image_0000001335316714.gif)
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![zh-cn_image_0000001335477142](figures/zh-cn_image_0000001335477142.gif)
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![zh-cn_image_0000001385757965](figures/zh-cn_image_0000001385757965.gif)
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![zh-cn_image_0000001335640862](figures/zh-cn_image_0000001335640862.gif)
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![zh-cn_image_0000001335641246](figures/zh-cn_image_0000001335641246.gif)
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![zh-cn_image_0000001335485154](figures/zh-cn_image_0000001335485154.gif)
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![zh-cn_image_0000001385645821](figures/zh-cn_image_0000001385645821.gif)
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