1# Flex
2
3Flex是以弹性方式布局子组件的容器组件,提供更加有效的方式对容器内的子元素进行排列、对齐和分配剩余空间。
4
5具体指南请参考[弹性布局](../../../ui/arkts-layout-development-flex-layout.md)。
6
7> **说明:**
8>
9> - 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
10> - Flex组件在渲染时存在二次布局过程,因此在对性能有严格要求的场景下建议使用[Column](ts-container-column.md)、[Row](ts-container-row.md)代替。
11> - Flex组件主轴默认不设置时撑满父容器,[Column](ts-container-column.md)、[Row](ts-container-row.md)组件主轴不设置时默认是跟随子节点大小。
12> - 主轴长度可设置为auto使Flex自适应子组件布局,自适应时,Flex长度受constraintSize属性以及父容器传递的最大最小长度限制且constraintSize属性优先级更高。
13
14
15## 子组件
16
17可以包含子组件。
18
19
20## 接口
21
22Flex(value?: FlexOptions)
23
24Flex布局容器。
25
26**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。
27
28**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
29
30**系统能力:** SystemCapability.ArkUI.ArkUI.Full
31
32**参数:**
33
34| 参数名            | 类型        | 必填   | 说明                                     |
35| -------------- | ---------------------------------------- | ---- |  ---------------------------------------- |
36| value      | [FlexOptions](#flexoptions对象说明) | 否    |  弹性布局子组件参数。               |
37
38## FlexOptions对象说明
39
40表示Flex子组件的排列对齐方式。
41
42**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
43
44**系统能力:** SystemCapability.ArkUI.ArkUI.Full
45
46| 名称            | 类型        | 必填   | 说明                                     |
47| -------------- | ---------------------------------------- | ---- |  ---------------------------------------- |
48| direction      | [FlexDirection](ts-appendix-enums.md#flexdirection) | 否     | 子组件在Flex容器上排列的方向,即主轴的方向。<br/>**默认值:** FlexDirection.Row<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。               |
49| wrap           | [FlexWrap](ts-appendix-enums.md#flexwrap) | 否     | Flex容器是单行/列还是多行/列排列。<br/>**默认值:** FlexWrap.NoWrap<br/>**说明:** <br/>在多行布局时,通过交叉轴方向,确认新行堆叠方向。<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 |
50| justifyContent | [FlexAlign](ts-appendix-enums.md#flexalign) | 否     | 所有子组件在Flex容器主轴上的对齐格式。<br/>**默认值:** FlexAlign.Start<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。                    |
51| alignItems     | [ItemAlign](ts-appendix-enums.md#itemalign) | 否     | 所有子组件在Flex容器交叉轴上的对齐格式。 <br/>**默认值:** ItemAlign.Start<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。                 |
52| alignContent   | [FlexAlign](ts-appendix-enums.md#flexalign) | 否     | 交叉轴中有额外的空间时,多行内容的对齐方式。仅在wrap为Wrap或WrapReverse下生效。<br/>**默认值:** FlexAlign.Start<br/>**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。  |
53| space<sup>12+</sup>          | [FlexSpaceOptions<sup>12+</sup>](ts-container-flex.md#flexspaceoptions12) | 否   | 所有子组件在Flex容器主轴或交叉轴的间距。<br/>**默认值:** {main:LengthMetrics.px(0), cross:LengthMetrics.px(0)} <br/>space为负数、百分比或者justifyContent设置为FlexAlign.SpaceBetweenFlexAlign.SpaceAroundFlexAlign.SpaceEvenly时不生效。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。|
54
55## FlexSpaceOptions<sup>12+</sup>
56
57**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
58
59**系统能力:** SystemCapability.ArkUI.ArkUI.Full
60
61| 名称          | 类型        |  只读     | 可选      | 说明      |
62| ----------- | --------- | ----------- | --------- |----------- |
63| main   | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12)  | 否 | 是 | Flex容器主轴上的space。<br/> space: {main: LengthMetrics.unit(value)} |
64| cross  | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | 否 | 是 | Flex容器交叉轴上的space。<br/> space: {cross: LengthMetrics.unit(value)} |
65
66## 示例
67
68### 示例1(子组件排列方向)
69该示例通过设置direction实现不同的子组件排列方向效果。
70```ts
71// xxx.ets
72@Entry
73@Component
74struct FlexExample1 {
75  build() {
76    Column() {
77      Column({ space: 5 }) {
78        Text('direction:Row').fontSize(9).fontColor(0xCCCCCC).width('90%')
79        Flex({ direction: FlexDirection.Row }) { // 子组件在容器主轴上行布局
80          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
81          Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
82          Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
83          Text('4').width('20%').height(50).backgroundColor(0xD2B48C)
84        }
85        .height(70)
86        .width('90%')
87        .padding(10)
88        .backgroundColor(0xAFEEEE)
89
90        Text('direction:RowReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
91        Flex({ direction: FlexDirection.RowReverse }) { // 子组件在容器主轴上反向行布局
92          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
93          Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
94          Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
95          Text('4').width('20%').height(50).backgroundColor(0xD2B48C)
96        }
97        .height(70)
98        .width('90%')
99        .padding(10)
100        .backgroundColor(0xAFEEEE)
101
102        Text('direction:Column').fontSize(9).fontColor(0xCCCCCC).width('90%')
103        Flex({ direction: FlexDirection.Column }) { // 子组件在容器主轴上列布局
104          Text('1').width('100%').height(40).backgroundColor(0xF5DEB3)
105          Text('2').width('100%').height(40).backgroundColor(0xD2B48C)
106          Text('3').width('100%').height(40).backgroundColor(0xF5DEB3)
107          Text('4').width('100%').height(40).backgroundColor(0xD2B48C)
108        }
109        .height(160)
110        .width('90%')
111        .padding(10)
112        .backgroundColor(0xAFEEEE)
113
114        Text('direction:ColumnReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
115        Flex({ direction: FlexDirection.ColumnReverse }) { // 子组件在容器主轴上反向列布局
116          Text('1').width('100%').height(40).backgroundColor(0xF5DEB3)
117          Text('2').width('100%').height(40).backgroundColor(0xD2B48C)
118          Text('3').width('100%').height(40).backgroundColor(0xF5DEB3)
119          Text('4').width('100%').height(40).backgroundColor(0xD2B48C)
120        }
121        .height(160)
122        .width('90%')
123        .padding(10)
124        .backgroundColor(0xAFEEEE)
125      }.width('100%').margin({ top: 5 })
126    }.width('100%')
127  }
128}
129```
130
131![zh-cn_image_0000001219744189](figures/zh-cn_image_0000001219744189.PNG)
132
133### 示例2(子组件单/多行排列)
134该示例通过设置wrap实现子组件单行或多行的排列效果。
135```ts
136// xxx.ets
137@Entry
138@Component
139struct FlexExample2 {
140  build() {
141    Column() {
142      Column({ space: 5 }) {
143        Text('Wrap').fontSize(9).fontColor(0xCCCCCC).width('90%')
144        Flex({ wrap: FlexWrap.Wrap }) { // 子组件多行布局
145          Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
146          Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
147          Text('3').width('50%').height(50).backgroundColor(0xD2B48C)
148        }
149        .width('90%')
150        .padding(10)
151        .backgroundColor(0xAFEEEE)
152
153        Text('NoWrap').fontSize(9).fontColor(0xCCCCCC).width('90%')
154        Flex({ wrap: FlexWrap.NoWrap }) { // 子组件单行布局
155          Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
156          Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
157          Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
158        }
159        .width('90%')
160        .padding(10)
161        .backgroundColor(0xAFEEEE)
162
163        Text('WrapReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
164        Flex({ wrap: FlexWrap.WrapReverse , direction:FlexDirection.Row }) { // 子组件反向多行布局
165          Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
166          Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
167          Text('3').width('50%').height(50).backgroundColor(0xD2B48C)
168        }
169        .width('90%')
170        .height(120)
171        .padding(10)
172        .backgroundColor(0xAFEEEE)
173      }.width('100%').margin({ top: 5 })
174    }.width('100%')
175  }
176}
177```
178
179![zh-cn_image_0000001174264366](figures/zh-cn_image_0000001174264366.png)
180
181### 示例3(子组件在主轴上的对齐格式)
182该示例通过设置justifyContent实现子组件在主轴上不同的对齐效果。
183```ts
184// xxx.ets
185@Component
186struct JustifyContentFlex {
187  justifyContent : number = 0;
188
189  build() {
190    Flex({ justifyContent: this.justifyContent }) {
191      Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
192      Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
193      Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
194    }
195    .width('90%')
196    .padding(10)
197    .backgroundColor(0xAFEEEE)
198  }
199}
200
201@Entry
202@Component
203struct FlexExample3 {
204  build() {
205    Column() {
206      Column({ space: 5 }) {
207        Text('justifyContent:Start').fontSize(9).fontColor(0xCCCCCC).width('90%')
208        JustifyContentFlex({ justifyContent: FlexAlign.Start }) // 子组件在容器主轴上首端对齐
209
210        Text('justifyContent:Center').fontSize(9).fontColor(0xCCCCCC).width('90%')
211        JustifyContentFlex({ justifyContent: FlexAlign.Center }) // 子组件在容器主轴上居中对齐
212
213        Text('justifyContent:End').fontSize(9).fontColor(0xCCCCCC).width('90%')
214        JustifyContentFlex({ justifyContent: FlexAlign.End }) // 子组件在容器主轴上尾端对齐
215
216        Text('justifyContent:SpaceBetween').fontSize(9).fontColor(0xCCCCCC).width('90%')
217        JustifyContentFlex({ justifyContent: FlexAlign.SpaceBetween }) // 子组件在容器主轴上均分容器布局,第一个子组件与行首对齐,最后一个子组件与行尾对齐。
218
219        Text('justifyContent:SpaceAround').fontSize(9).fontColor(0xCCCCCC).width('90%')
220        JustifyContentFlex({ justifyContent: FlexAlign.SpaceAround }) // 子组件在容器主轴上均分容器布局,第一个子组件到行首的距离和最后一个子组件到行尾的距离是相邻子组件之间距离的一半。
221
222        Text('justifyContent:SpaceEvenly').fontSize(9).fontColor(0xCCCCCC).width('90%')
223        JustifyContentFlex({ justifyContent: FlexAlign.SpaceEvenly }) // 子组件在容器主轴上均分容器布局,子组件之间的距离与第一子组件到行首、最后一个子组件到行尾的距离相等
224      }.width('100%').margin({ top: 5 })
225    }.width('100%')
226  }
227}
228```
229
230![zh-cn_image_0000001174582854](figures/zh-cn_image_0000001174582854.PNG)
231
232### 示例4(子组件在交叉轴上的对齐方式)
233该示例通过设置alignItems实现子组件在主轴上的不同的对齐效果。
234```ts
235// xxx.ets
236@Component
237struct AlignItemsFlex {
238  alignItems : number = 0;
239
240  build() {
241    Flex({ alignItems: this.alignItems }) {
242      Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
243      Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
244      Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
245    }
246    .size({width: '90%', height: 80})
247    .padding(10)
248    .backgroundColor(0xAFEEEE)
249  }
250}
251
252@Entry
253@Component
254struct FlexExample4 {
255  build() {
256    Column() {
257      Column({ space: 5 }) {
258        Text('alignItems:Auto').fontSize(9).fontColor(0xCCCCCC).width('90%')
259        AlignItemsFlex({ alignItems: ItemAlign.Auto }) // 子组件在容器交叉轴上首部对齐
260
261        Text('alignItems:Start').fontSize(9).fontColor(0xCCCCCC).width('90%')
262        AlignItemsFlex({ alignItems: ItemAlign.Start }) // 子组件在容器交叉轴上首部对齐
263
264        Text('alignItems:Center').fontSize(9).fontColor(0xCCCCCC).width('90%')
265        AlignItemsFlex({ alignItems: ItemAlign.Center }) // 子组件在容器交叉轴上居中对齐
266
267        Text('alignItems:End').fontSize(9).fontColor(0xCCCCCC).width('90%')
268        AlignItemsFlex({ alignItems: ItemAlign.End }) // 子组件在容器交叉轴上尾部对齐
269
270        Text('alignItems:Stretch').fontSize(9).fontColor(0xCCCCCC).width('90%')
271        AlignItemsFlex({ alignItems: ItemAlign.Stretch }) // 子组件在容器交叉轴上拉伸填充
272
273        Text('alignItems:Baseline').fontSize(9).fontColor(0xCCCCCC).width('90%')
274        AlignItemsFlex({ alignItems: ItemAlign.Baseline }) // 子组件在容器交叉轴上与文本基线对齐
275      }.width('100%').margin({ top: 5 })
276    }.width('100%')
277  }
278}
279```
280
281![zh-cn_image_0000001174422904](figures/zh-cn_image_0000001174422904.png)
282
283### 示例5(多行内容的对齐方式)
284该示例通过设置alignContent实现多行内容的不同对齐效果。
285```ts
286// xxx.ets
287@Component
288struct AlignContentFlex {
289  alignContent: number = 0;
290
291  build() {
292    Flex({ wrap: FlexWrap.Wrap, alignContent: this.alignContent }) {
293      Text('1').width('50%').height(20).backgroundColor(0xF5DEB3)
294      Text('2').width('50%').height(20).backgroundColor(0xD2B48C)
295      Text('3').width('50%').height(20).backgroundColor(0xD2B48C)
296    }
297    .size({ width: '90%', height: 90 })
298    .padding(10)
299    .backgroundColor(0xAFEEEE)
300  }
301}
302
303@Entry
304@Component
305struct FlexExample5 {
306  build() {
307    Column() {
308      Column({ space: 5 }) {
309        Text('alignContent:Start').fontSize(9).fontColor(0xCCCCCC).width('90%')
310        AlignContentFlex({ alignContent: FlexAlign.Start }) // 多行布局下子组件首部对齐
311
312        Text('alignContent:Center').fontSize(9).fontColor(0xCCCCCC).width('90%')
313        AlignContentFlex({ alignContent: FlexAlign.Center }) // 多行布局下子组件居中对齐
314
315        Text('alignContent:End').fontSize(9).fontColor(0xCCCCCC).width('90%')
316        AlignContentFlex({ alignContent: FlexAlign.End }) // 多行布局下子组件尾部对齐
317
318        Text('alignContent:SpaceBetween').fontSize(9).fontColor(0xCCCCCC).width('90%')
319        AlignContentFlex({ alignContent: FlexAlign.SpaceBetween }) // 多行布局下第一行子组件与列首对齐,最后一行子组件与列尾对齐
320
321        Text('alignContent:SpaceAround').fontSize(9).fontColor(0xCCCCCC).width('90%')
322        AlignContentFlex({ alignContent: FlexAlign.SpaceAround }) // 多行布局下第一行子组件到列首的距离和最后一行子组件到列尾的距离是相邻行之间距离的一半
323
324        Text('alignContent:SpaceEvenly').fontSize(9).fontColor(0xCCCCCC).width('90%')
325        Flex({
326          wrap: FlexWrap.Wrap,
327          alignContent: FlexAlign.SpaceEvenly
328        }) { // 多行布局下相邻行之间的距离与第一行子组件到列首的距离、最后一行子组件到列尾的距离完全一样
329          Text('1').width('50%').height(20).backgroundColor(0xF5DEB3)
330          Text('2').width('50%').height(20).backgroundColor(0xD2B48C)
331          Text('3').width('50%').height(20).backgroundColor(0xF5DEB3)
332          Text('4').width('50%').height(20).backgroundColor(0xD2B48C)
333          Text('5').width('50%').height(20).backgroundColor(0xF5DEB3)
334        }
335        .size({ width: '90%', height: 100 })
336        .padding({ left: 10, right: 10 })
337        .backgroundColor(0xAFEEEE)
338      }.width('100%').margin({ top: 5 })
339    }.width('100%')
340  }
341}
342```
343
344![zh-cn_image_0000001174422906](figures/zh-cn_image_0000001174422906.PNG)
345
346### 示例6(子组件单/多行排列时的主/交叉轴间距)
347该示例通过设置space为单/多行排列的子组件确定在主/交叉轴上的间距。
348```ts
349import {LengthMetrics} from '@kit.ArkUI';
350
351@Entry
352@Component
353struct FlexExample2 {
354  build() {
355    Column() {
356      Column({ space: 5 }) {
357        Text('Wrap').fontSize(9).fontColor(0xCCCCCC).width('90%')
358        Flex({ wrap: FlexWrap.Wrap, space: {main: LengthMetrics.px(50), cross: LengthMetrics.px(50)} }) { // 子组件多行布局
359          Text('1').width('40%').height(50).backgroundColor(0xF5DEB3)
360          Text('2').width('40%').height(50).backgroundColor(0xD2B48C)
361          Text('3').width('40%').height(50).backgroundColor(0xD2B48C)
362        }
363        .width('90%')
364        .padding(10)
365        .backgroundColor(0xAFEEEE)
366
367        Text('NoWrap').fontSize(9).fontColor(0xCCCCCC).width('90%')
368        Flex({ wrap: FlexWrap.NoWrap, space: {main: LengthMetrics.px(50), cross: LengthMetrics.px(50)} }) { // 子组件单行布局
369          Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
370          Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
371          Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
372        }
373        .width('90%')
374        .padding(10)
375        .backgroundColor(0xAFEEEE)
376
377        Text('WrapReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
378        Flex({ wrap: FlexWrap.WrapReverse, direction:FlexDirection.Row, space: {main: LengthMetrics.px(50), cross: LengthMetrics.px(50)} }) { // 子组件反向多行布局
379          Text('1').width('40%').height(50).backgroundColor(0xF5DEB3)
380          Text('2').width('40%').height(50).backgroundColor(0xD2B48C)
381          Text('3').width('40%').height(50).backgroundColor(0xD2B48C)
382        }
383        .width('90%')
384        .height(120)
385        .padding(10)
386        .backgroundColor(0xAFEEEE)
387      }.width('100%').margin({ top: 5 })
388    }.width('100%')
389  }
390}
391```
392
393![zh-cn_image_0000001174422907](figures/zh-cn_image_0000001174422907.PNG)
394
395### 示例7(宽度自适应的Flex容器)
396该示例实现了Flex在宽度设置auto后可以自适应子组件布局的能力。
397```ts
398@Component
399struct Demo {
400  @Require @Prop text: string
401
402  build() {
403    Button() {
404      Flex() {
405        Image($r('sys.media.ohos_ic_public_voice'))
406          .width(16)
407          .height(16)
408
409        Row() {
410          Text(this.text)
411            .margin({
412              left: 6,
413              right: 6
414            })
415            .fontSize(14)
416            .maxLines(1)
417            .textOverflow({ overflow: TextOverflow.Ellipsis })
418        }
419
420        Image($r('sys.media.ohos_ic_public_sound'))
421          .width(16)
422          .height(16)
423      }.width("auto")
424    }
425    .backgroundColor(0xAFEEEE)
426    .height(36)
427    .padding({ left: 16, right: 16 })
428    .constraintSize({ maxWidth: 156 })
429    .width("auto")
430  }
431}
432
433@Entry
434@Component
435struct Index {
436  build() {
437    Column({ space: 12 }) {
438      Text("Width does not reach max length").fontSize(11).fontColor(0XCCCCCC).width("50%")
439      Demo({ text: "123" })
440      Text("Width reaches max length").fontSize(11).fontColor(0XCCCCCC).width("50%")
441      Demo({ text: "1234567890-1234567890-1234567890-1234567890" })
442    }
443  }
444}
445```
446
447![zh-cn_flexDemo_7](figures/zh-cn_flexDemo_7.png)
448