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.SpaceBetween、FlexAlign.SpaceAround、FlexAlign.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 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 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 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 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 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 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 448