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