1# Custom Component Layout 2 3The custom layout of a custom component is used to lay out its child components through data calculation. 4 5> **NOTE** 6> 7> The initial APIs of this module are supported since API version 9. Newly added APIs will be marked with a superscript to indicate their earliest API version. 8 9## onPlaceChildren<sup>10+</sup> 10 11onPlaceChildren?(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions):void 12 13Invoked when the custom component lays out its child components. Through this callback the component receives its child component size constraints from the ArkUI framework. State variables should not be changed in this callback. 14 15**System capability**: SystemCapability.ArkUI.ArkUI.Full 16 17**Atomic service API**: This API can be used in atomic services since API version 11. 18 19**Parameters** 20 21| Name | Type | Description | 22|----------------|------------------------------------------------------------|------------------| 23| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | Layout information of the parent component. | 24| children | Array<[Layoutable](#layoutable10)> | Child component layout information. | 25| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Size constraint of the parent component.| 26 27## onMeasureSize<sup>10+</sup> 28 29onMeasureSize?(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions): SizeResult 30 31Invoked when the custom component needs to determine its size. Through this callback the component receives its child component layout information and size constraint from the ArkUI framework. State variables should not be changed in this callback. 32 33**System capability**: SystemCapability.ArkUI.ArkUI.Full 34 35**Atomic service API**: This API can be used in atomic services since API version 11. 36 37**Parameters** 38 39| Name | Type | Description | 40| -------------- | ---------------------------------------------------------- | ------------------------------------------------------------ | 41| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | Layout information of the parent component. | 42| children | Array<[Measurable](#measurable10)> | Child component layout information.<br>**NOTE**<br>When a child component does not have its layout information set, it retains the previous layout settings or, if no previous layout settings are available, stays at the default size of 0.| 43| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Size constraint of the parent component. | 44 45**Return value** 46 47| Type | Description | 48| --------------------------- | -------------- | 49| [SizeResult](#sizeresult10) | Component size information.| 50 51## GeometryInfo<sup>10+</sup> 52 53Provides the parent component layout information. Inherits from [SizeResult](#sizeresult10). 54 55**System capability**: SystemCapability.ArkUI.ArkUI.Full 56 57**Atomic service API**: This API can be used in atomic services since API version 11. 58 59| Name | Type | Description | 60|-------------|-----------|---------------------| 61| borderWidth | [EdgeWidth](ts-types.md#edgewidths9) | Border width of the parent component.<br>Unit: vp | 62| margin | [Margin](ts-types.md#margin) | Margin of the parent component.<br>Unit: vp | 63| padding | [Padding](ts-types.md#padding) | Padding of the parent component.<br>Unit: vp| 64| width | number | Width obtained from the measurement result.<br>Unit: vp<br> **NOTE**<br>If the value is empty, the component width in percentage is returned.| 65| height | number | Height obtained from the measurement result.<br>Unit: vp<br> **NOTE**<br>If the value is empty, the component height in percentage is returned.| 66 67 68## Layoutable<sup>10+</sup> 69 70Provides the child component layout information. 71 72**System capability**: SystemCapability.ArkUI.ArkUI.Full 73 74### Name 75 76| Name | Type | Mandatory | Description | 77|--------------|---------------------------------- | -----------------------------------------------|---------------------| 78| measureResult| [MeasureResult](#measureresult10) | Yes| Measurement result of the child component. Inherits from [SizeResult](#sizeresult10).<br>**Atomic service API**: This API can be used in atomic services since API version 11.<br>Unit: vp | 79 80 81### layout 82 83layout(position: Position) 84 85Applies the specified position information to the child component. 86 87**Atomic service API**: This API can be used in atomic services since API version 11. 88 89**System capability**: SystemCapability.ArkUI.ArkUI.Full 90 91**Parameters** 92 93| Name | Type | Mandatory |Description | 94|-----------------|---------------------------------------------------------|---------------------|-------------| 95| position | [Position](ts-types.md#position) | Yes | Position. | 96 97### getMargin<sup>12+</sup> 98 99getMargin() : DirectionalEdgesT\<number> 100 101Obtains the margin of the child component. 102 103**Return value** 104 105| Type | Description | 106|------------------------------------|---------------------------------------------| 107| [DirectionalEdgesT<number>](#directionaledgestt12) | Margin of the child component. | 108 109 ### getPadding<sup>12+</sup> 110 111getPadding() : DirectionalEdgesT\<number> 112 113 Obtains the padding of the child component. 114 115 **Return value** 116 117| Type | Description | 118|------------------------------------|---------------------------------------------| 119| [DirectionalEdgesT<number>](#directionaledgestt12) | Padding of the child component. | 120 121### getBorderWidth<sup>12+</sup> 122 123getBorderWidth() : DirectionalEdgesT\<number> 124 125Obtains the border width of the child component. 126 127**Return value** 128 129| Type | Description | 130|------------------------------------|---------------------------------------------| 131| [DirectionalEdgesT<number>](#directionaledgestt12) | Border width of the child component. | 132 133## Measurable<sup>10+</sup> 134 135Provides the child component position information. 136 137**System capability**: SystemCapability.ArkUI.ArkUI.Full 138 139**Atomic service API**: This API can be used in atomic services since API version 11. 140 141### measure 142 143 measure(constraint: ConstraintSizeOptions) : MeasureResult 144 145 Applies the size constraint to the child component. 146 147 **System capability**: SystemCapability.ArkUI.ArkUI.Full 148 149**Atomic service API**: This API can be used in atomic services since API version 11. 150 151**Parameters** 152 153| Name | Type | Mandatory |Description | 154|-----------------|---------------------------------------------------------|---------------------|-------------| 155| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes | Size constraint. | 156 157**Return value** 158 159 | Type | Description | 160 |------------------------------------|-------------------------| 161 |[MeasureResult](#measureresult10) | Provides the measurement result of the component. | 162 163 ### getMargin<sup>12+</sup> 164 165 getMargin() : DirectionalEdgesT\<number\> 166 167 Obtains the padding of the child component. 168 169**System capability**: SystemCapability.ArkUI.ArkUI.Full 170 171**Atomic service API**: This API can be used in atomic services since API version 12. 172 173**Return value** 174 175 | Type | Description | 176 |------------------------------------|-------------------------| 177 |[DirectionalEdgesT<number>](#directionaledgestt12) | Margin of the child component. | 178 179### getPadding<sup>12+</sup> 180 181getPadding() : DirectionalEdgesT\<number\> 182 183Obtains the padding of the child component. 184 185**System capability**: SystemCapability.ArkUI.ArkUI.Full 186 187**Atomic service API**: This API can be used in atomic services since API version 12. 188 189**Return value** 190 191 | Type | Description | 192 |------------------------------------|-------------------------| 193 |[DirectionalEdgesT<number>](#directionaledgestt12) | Padding of the child component. | 194 195 ### getBorderWidth<sup>12+</sup> 196 197getBorderWidth() : DirectionalEdgesT\<number\> 198 199Obtains the border widthof the child component. 200 201**System capability**: SystemCapability.ArkUI.ArkUI.Full 202 203**Atomic service API**: This API can be used in atomic services since API version 12. 204 205**Return value** 206 207 | Type | Description | 208 |------------------------------------|-------------------------| 209 |[DirectionalEdgesT<number>](#directionaledgestt12) | Border width of the child component.| 210 211 212## MeasureResult<sup>10+</sup> 213 214Provides the measurement result of the component. 215 216**System capability**: SystemCapability.ArkUI.ArkUI.Full 217 218**Atomic service API**: This API can be used in atomic services since API version 11. 219 220| Name | Type | Description | 221|--------|--------|-------| 222| width | number | Width obtained from the measurement result.<br>Unit: vp| 223| height | number | Height obtained from the measurement result.<br>Unit: vp| 224 225 226## SizeResult<sup>10+</sup> 227 228Provides the component size information. 229 230**System capability**: SystemCapability.ArkUI.ArkUI.Full 231 232**Atomic service API**: This API can be used in atomic services since API version 11. 233 234| Name | Type | Description | 235|--------|--------|-------| 236| width | number | Width obtained from the measurement result.<br>Unit: vp| 237| height | number | Height obtained from the measurement result.<br>Unit: vp| 238 239## DirectionalEdgesT\<T><sup>12+</sup> 240 241Defines the directional edges. 242 243**System capability**: SystemCapability.ArkUI.ArkUI.Full 244 245**Widget capability**: This API can be used in ArkTS widgets since API version 12. 246 247| Name | Type| Description | 248| ------ | ---- | ---------------- | 249| start | T | Start edge. It is the left edge if the direction is left-to-right and the right edge if the direction is right-to-left.| 250| end | T | End edge. It is the right edge if the direction is left-to-right and the left edge if the direction is right-to-left.| 251| top | T | Top edge.| 252| bottom | T | Top edge.| 253 254> **NOTE** 255> 256>- The custom layout does not support the LazyForEach syntax. 257>- When a custom layout is created in builder mode, only **this.builder()** is allowed in the **build()** method of a custom component, as shown in the recommended usage in the example below. 258>- The size parameters of the parent component (custom component), except **aspectRatio**, are at a lower priority than those specified by **onMeasureSize**. 259>- The position parameters of the child component, except **offset**, **position**, and **markAnchor**, are at a lower priority than those specified by **onPlaceChildren**, and do not take effect. 260>- When using the custom layout method, you must call **onMeasureSize** and **onPlaceChildren** at the same time for the layout to display properly. 261 262**Example 1** 263This example demonstrates how to customize a layout. 264``` 265// xxx.ets 266@Entry 267@Component 268struct Index { 269 build() { 270 Column() { 271 CustomLayout({ builder: ColumnChildren }) 272 } 273 } 274} 275 276@Builder 277function ColumnChildren() { 278 ForEach([1, 2, 3], (index: number) => {// LazyForEach is not supported. 279 Text('S' + index) 280 .fontSize(30) 281 .width(100) 282 .height(100) 283 .borderWidth(2) 284 .offset({ x: 10, y: 20 }) 285 }) 286} 287 288@Component 289struct CustomLayout { 290 @Builder 291 doNothingBuilder() { 292 }; 293 294 @BuilderParam builder: () => void = this.doNothingBuilder; 295 @State startSize: number = 100; 296 result: SizeResult = { 297 width: 0, 298 height: 0 299 }; 300 301 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 302 let startPos = 300; 303 children.forEach((child) => { 304 let pos = startPos - child.measureResult.height; 305 child.layout({ x: pos, y: pos }) 306 }) 307 } 308 309 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 310 let size = 100; 311 children.forEach((child) => { 312 let result: MeasureResult = child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 313 size += result.width / 2 314 ; 315 }) 316 this.result.width = 100; 317 this.result.height = 400; 318 return this.result; 319 } 320 321 build() { 322 this.builder() 323 } 324} 325``` 326 327 328 329**Example 2** 330This example shows how to determine whether a component participates in layout calculation based on its position. 331``` 332// xxx.ets 333@Entry 334@Component 335struct Index { 336 build() { 337 Column() { 338 CustomLayout({ builder: ColumnChildren }) 339 } 340 .justifyContent(FlexAlign.Center) 341 .width("100%") 342 .height("100%") 343 } 344} 345 346@Builder 347function ColumnChildren() { 348 ForEach([1, 2, 3], (item: number, index: number) => { // LazyForEach is not supported. 349 Text('S' + item) 350 .fontSize(20) 351 .width(60 + 10 * index) 352 .height(100) 353 .borderWidth(2) 354 .margin({ left:10 }) 355 .padding(10) 356 }) 357} 358 359@Component 360struct CustomLayout { 361 // Lay out only one row, and hide child components that are too large for the available space. 362 @Builder 363 doNothingBuilder() { 364 }; 365 366 @BuilderParam builder: () => void = this.doNothingBuilder; 367 result: SizeResult = { 368 width: 0, 369 height: 0 370 }; 371 overFlowIndex: number = -1; 372 373 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 374 let currentX = 0; 375 let infinity = 100000; 376 if (this.overFlowIndex == -1) { 377 this.overFlowIndex = children.length; 378 } 379 for (let index = 0; index < children.length; ++index) { 380 let child = children[index]; 381 if (index >= this.overFlowIndex) { 382 // Hide any child component that extends beyond the area of its parent component by placing it in a distant position. 383 child.layout({x: infinity, y: 0}); 384 continue; 385 } 386 child.layout({ x: currentX, y: 0 }) 387 let margin = child.getMargin(); 388 currentX += child.measureResult.width + margin.start + margin.end; 389 } 390 } 391 392 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 393 let width = 0; 394 let height = 0; 395 this.overFlowIndex = -1; 396 // Assume that the component width cannot exceed 200 vp or the maximum constraint. 397 let maxWidth = Math.min(200, constraint.maxWidth as number); 398 for (let index = 0; index < children.length; ++index) { 399 let child = children[index]; 400 let childResult: MeasureResult = child.measure({ 401 minHeight: constraint.minHeight, 402 minWidth: constraint.minWidth, 403 maxWidth: constraint.maxWidth, 404 maxHeight: constraint.maxHeight 405 }) 406 let margin = child.getMargin(); 407 let newWidth = width + childResult.width + margin.start + margin.end; 408 if (newWidth > maxWidth) { 409 // Record the index of the component that should not be laid out. 410 this.overFlowIndex = index; 411 break; 412 } 413 // Accumulate the width and height of the parent component. 414 width = newWidth; 415 height = Math.max(height, childResult.height + margin.top + margin.bottom); 416 } 417 this.result.width = width; 418 this.result.height = height; 419 return this.result; 420 } 421 422 build() { 423 this.builder() 424 } 425} 426``` 427 428 429 430## onLayout<sup>(deprecated)</sup> 431 432onLayout?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 433 434Invoked when the custom component lays out its child components. Through this callback the component receives its child component layout information and size constraint from the ArkUI framework. State variables should not be changed in this callback. 435 436This API is supported since API version 9 and deprecated since API version 10. You are advised to use [onPlaceChildren](#onplacechildren10) instead. 437 438**Parameters** 439 440| Name | Type | Description | 441|------------|------------------------------------------------------------|------------------| 442| children | Array<[LayoutChild](#layoutchilddeprecated)> | Child component layout information. | 443| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Size constraint of the parent component.| 444 445## onMeasure<sup>(deprecated)</sup> 446 447onMeasure?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 448 449Invoked when the custom component needs to determine its size. Through this callback the component receives its child component layout information and size constraint from the ArkUI framework. State variables should not be changed in this callback. 450 451This API is supported since API version 9 and deprecated since API version 10. You are advised to use [onMeasureSize](#onmeasuresize10) instead. 452 453**Parameters** 454 455| Name | Type | Description | 456|------------|------------------------------------------------------------|------------------| 457| children | Array<[LayoutChild](#layoutchilddeprecated)> | Child component layout information. | 458| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Size constraint of the parent component.| 459 460## LayoutChild<sup>(deprecated)</sup> 461 462Child component layout information. 463 464This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 465 466 467| Name | Type | Description | 468| ---------- | ------------------------------------------------------------ | -------------------------------------- | 469| name | string | Name of the child component. | 470| id | string | ID of the child component. | 471| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Constraint size of the child component. | 472| borderInfo | [LayoutBorderInfo](#layoutborderinfodeprecated) | Provides the border information of the child component. | 473| position | [Position](ts-types.md#position) | Position coordinates of the child component. | 474| measure | (childConstraint: [ConstraintSizeOptions](ts-types.md#constraintsizeoptions)) => void | Method called to apply the size constraint to the child component.| 475| layout | (LayoutInfo: [LayoutInfo](#layoutinfodeprecated)) => void | Method called to apply the specified position information to the child component.| 476 477## LayoutBorderInfo<sup>(deprecated)</sup> 478 479Provides the border information of the child component. 480 481This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 482 483| Name | Type | Description | 484|-------------|--------------------------------------|-------------------------| 485| borderWidth | [EdgeWidths](ts-types.md#edgewidths9) | Edge widths in different directions of the component.| 486| margin | [Margin](ts-types.md#margin) | Margins in different directions of the component. | 487| padding | [Padding](ts-types.md#padding) | Paddings in different directions of the component. | 488 489## LayoutInfo<sup>(deprecated)</sup> 490 491Provides the layout information of the child component. 492 493This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 494 495| Name | Type | Description | 496| ---------- | ---------------------------------------------------------- | ---------------- | 497| position | [Position](ts-types.md#position) | Position coordinates of the child component.| 498| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Constraint size of the child component.| 499 500The layout can be modified through **layout**. 501```ts 502// xxx.ets 503@Entry 504@Component 505struct Index { 506 build() { 507 Column() { 508 CustomLayout() { 509 ForEach([1, 2, 3], (index: number) => { 510 Text('Sub' + index) 511 .fontSize(30) 512 .borderWidth(2) 513 }) 514 } 515 } 516 } 517} 518 519 520@Component 521struct CustomLayout { 522 @Builder 523 doNothingBuilder() { 524 }; 525 526 @BuilderParam builder: () => void = this.doNothingBuilder; 527 528 onLayout(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 529 let pos = 0; 530 children.forEach((child) => { 531 child.layout({ position: { x: pos, y: pos }, constraint: constraint }) 532 pos += 70; 533 }) 534 } 535 536 onMeasure(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 537 let size = 100; 538 children.forEach((child) => { 539 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 540 size += 50; 541 }) 542 } 543 544 build() { 545 this.builder() 546 } 547} 548``` 549 550 551