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