1# Custom Component Layout 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @song-song-song--> 5<!--Designer: @lanshouren--> 6<!--Tester: @liuli0427--> 7<!--Adviser: @HelloCrease--> 8 9The custom layout of a custom component is used to lay out its child components through data calculation. 10 11> **NOTE** 12> 13> 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. 14> 15> A custom component is considered to have a custom layout when either of the **onMeasureSize** or **onPlaceChildren** methods is implemented. For complete layout control, implement both methods simultaneously. For details about the specifications, see the API descriptions for these methods. 16> 17> Since API version 20, when child components within a custom layout have their [LayoutPolicy](ts-types.md#layoutpolicy15) object's **fixAtIdealSize** property set to **true**, these components will ignore any layout constraints from their parent component. Instead, they will adhere to the size ranges explicitly defined by the developer in the custom layout implementation. 18> 19> Lazy loading (including [Repeat](../../../ui/state-management/arkts-new-rendering-control-repeat.md) and [LazyForEach](../../../ui/state-management/arkts-rendering-control-lazyforeach.md)) is not supported in custom layouts. 20 21## onMeasureSize<sup>10+</sup> 22 23onMeasureSize?(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions): SizeResult 24 25Invoked when the custom component needs to determine its size. Through this callback the component receives its layout information and size constraints from the ArkUI framework. State variables should not be changed in this callback. 26 27**Atomic service API**: This API can be used in atomic services since API version 11. 28 29**System capability**: SystemCapability.ArkUI.ArkUI.Full 30 31**Parameters** 32 33| Name | Type | Mandatory|Description | 34| -------------- | ---------------------------------------------------------- | ---|------------------------------------------------------------ | 35| selfLayoutInfo | [GeometryInfo](#geometryinfo10) | Yes|Information about the component's computed layout properties after measurement.<br>**NOTE**<br>During the first layout, the component will use its own set attributes as the basis for layout. | 36| children | Array<[Measurable](#measurable10)> | Yes|Array containing layout information for all child components after measurement.<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.| 37| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes|Layout constraints applied to the component. | 38 39**Return value** 40 41| Type | Description | 42| --------------------------- | -------------- | 43| [SizeResult](#sizeresult10) | Component size information.| 44 45## onPlaceChildren<sup>10+</sup> 46 47onPlaceChildren?(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions):void 48 49Invoked when the custom component needs to determine the positions of 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. 50 51**Atomic service API**: This API can be used in atomic services since API version 11. 52 53**System capability**: SystemCapability.ArkUI.ArkUI.Full 54 55**Parameters** 56 57| Name | Type |Mandatory| Description | 58|----------------|------------------------------------------------------------|---|------------------| 59| selfLayoutInfo | [GeometryInfo](#geometryinfo10) |Yes|Information about the component's computed layout properties after measurement. | 60| children | Array<[Layoutable](#layoutable10)> |Yes|Array containing layout information for all child components after measurement. | 61| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) |Yes|Layout constraints applied to the component.| 62 63**Example** 64 65See the [example for customizing a layout](#example). 66 67## GeometryInfo<sup>10+</sup> 68 69Provides the parent component layout information. Inherits from [SizeResult](#sizeresult10). 70 71**Atomic service API**: This API can be used in atomic services since API version 11. 72 73**System capability**: SystemCapability.ArkUI.ArkUI.Full 74 75| Name | Type |Read-Only|Optional| Description | 76|-------------|-----------|------|------|---------------------| 77| borderWidth | [EdgeWidth](ts-types.md#edgewidths9) |No|No| Border width of the parent component.<br>Unit: vp | 78| margin | [Margin](ts-types.md#margin) | No|No|Margin of the parent component.<br>Unit: vp | 79| padding | [Padding](ts-types.md#padding) |No|No| Padding of the parent component.<br>Unit: vp| 80 81## Layoutable<sup>10+</sup> 82 83Provides the child component layout information. 84 85**System capability**: SystemCapability.ArkUI.ArkUI.Full 86 87### Name 88 89| Name | Type | Read-Only|Optional| Description | 90|--------------|---------------------------------- | ------|-----------------------------------------------------|---------------------| 91| measureResult| [MeasureResult](#measureresult10) | No|No| Measurement result of the child component.<br>**Atomic service API**: This API can be used in atomic services since API version 11.<br>Unit: vp | 92| uniqueId<sup>18+</sup>| number | No|No| Unique ID that the system assigns to the child component.<br>Value range: [0, +∞).<br>**Atomic service API**: This API can be used in atomic services since API version 18.| 93 94### layout 95 96layout(position: Position) 97 98Applies the specified position information to the child component. 99 100**Atomic service API**: This API can be used in atomic services since API version 11. 101 102**System capability**: SystemCapability.ArkUI.ArkUI.Full 103 104**Parameters** 105 106| Name | Type | Mandatory |Description | 107|-----------------|---------------------------------------------------------|---------------------|-------------| 108| position | [Position](ts-types.md#position) | Yes | Absolute position. | 109 110### getMargin<sup>12+</sup> 111 112getMargin() : DirectionalEdgesT\<number> 113 114Obtains the margin values of the child component. 115 116**Atomic service API**: This API can be used in atomic services since API version 12. 117 118**System capability**: SystemCapability.ArkUI.ArkUI.Full 119 120**Return value** 121 122| Type | Description | 123|------------------------------------|---------------------------------------------| 124| [DirectionalEdgesT<number>](#directionaledgestt12) | Margin values of the child component. | 125 126 ### getPadding<sup>12+</sup> 127 128getPadding() : DirectionalEdgesT\<number> 129 130 Obtains the padding values of the child component. 131 132**Atomic service API**: This API can be used in atomic services since API version 12. 133 134**System capability**: SystemCapability.ArkUI.ArkUI.Full 135 136 **Return value** 137 138| Type | Description | 139|------------------------------------|---------------------------------------------| 140| [DirectionalEdgesT<number>](#directionaledgestt12) | Padding values of the child component. | 141 142### getBorderWidth<sup>12+</sup> 143 144getBorderWidth() : DirectionalEdgesT\<number> 145 146Obtains the border widths of the child component. 147 148**Atomic service API**: This API can be used in atomic services since API version 12. 149 150**System capability**: SystemCapability.ArkUI.ArkUI.Full 151 152**Return value** 153 154| Type | Description | 155|------------------------------------|---------------------------------------------| 156| [DirectionalEdgesT<number>](#directionaledgestt12) | Border widths of the child component. | 157 158## Measurable<sup>10+</sup> 159 160Provides the child component position information. 161 162**Atomic service API**: This API can be used in atomic services since API version 11. 163 164**System capability**: SystemCapability.ArkUI.ArkUI.Full 165 166### Name 167 168**Atomic service API**: This API can be used in atomic services since API version 18. 169 170**System capability**: SystemCapability.ArkUI.ArkUI.Full 171 172| Name | Type | Mandatory | Description | 173|--------------|---------------------------------- | -----------------------------------------------|---------------------| 174| uniqueId<sup>18+</sup>| number | No| Unique ID that the system assigns to the child component.| 175 176### measure 177 178 measure(constraint: ConstraintSizeOptions) : MeasureResult 179 180 Imposes size constraints on the child component. 181 182 **Atomic service API**: This API can be used in atomic services since API version 11. 183 184 **System capability**: SystemCapability.ArkUI.ArkUI.Full 185 186 187**Parameters** 188 189| Name | Type | Mandatory |Description | 190|-----------------|---------------------------------------------------------|---------------------|-------------| 191| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes | Size constraint. | 192 193**Return value** 194 195 | Type | Description | 196 |------------------------------------|-------------------------| 197 |[MeasureResult](#measureresult10) | Provides the measurement result of the component. | 198 199 ### getMargin<sup>12+</sup> 200 201 getMargin() : DirectionalEdgesT\<number\> 202 203 Obtains the margin values of the child component. 204 205**Atomic service API**: This API can be used in atomic services since API version 12. 206 207**System capability**: SystemCapability.ArkUI.ArkUI.Full 208 209**Return value** 210 211 | Type | Description | 212 |------------------------------------|-------------------------| 213 |[DirectionalEdgesT<number>](#directionaledgestt12) | Margin values of the child component. | 214 215### getPadding<sup>12+</sup> 216 217getPadding() : DirectionalEdgesT\<number\> 218 219Obtains the padding values of the child component. 220 221**Atomic service API**: This API can be used in atomic services since API version 12. 222 223**System capability**: SystemCapability.ArkUI.ArkUI.Full 224 225**Return value** 226 227 | Type | Description | 228 |------------------------------------|-------------------------| 229 |[DirectionalEdgesT<number>](#directionaledgestt12) | Padding values of the child component. | 230 231 ### getBorderWidth<sup>12+</sup> 232 233getBorderWidth() : DirectionalEdgesT\<number\> 234 235Obtains the border widths of the child component. 236 237**Atomic service API**: This API can be used in atomic services since API version 12. 238 239**System capability**: SystemCapability.ArkUI.ArkUI.Full 240 241**Return value** 242 243 | Type | Description | 244 |------------------------------------|-------------------------| 245 |[DirectionalEdgesT<number>](#directionaledgestt12) | Border widths of the child component.| 246 247 248## MeasureResult<sup>10+</sup> 249 250Provides the measurement result of the component. This API inherits from [SizeResult] (#sizeresult10). 251 252**Atomic service API**: This API can be used in atomic services since API version 11. 253 254**System capability**: SystemCapability.ArkUI.ArkUI.Full 255 256## SizeResult<sup>10+</sup> 257 258Provides the component size information. 259 260**Atomic service API**: This API can be used in atomic services since API version 11. 261 262**System capability**: SystemCapability.ArkUI.ArkUI.Full 263 264| Name | Type |Read-Only|Optional| Description | 265|--------|--------|------|------|-------| 266| width | number | No|No|Width obtained from the measurement result.<br>Unit: vp| 267| height | number | No|No|Height obtained from the measurement result.<br>Unit: vp| 268 269## DirectionalEdgesT\<T><sup>12+</sup> 270 271Defines the directional edges. 272 273**Widget capability**: This API can be used in ArkTS widgets since API version 12. 274 275**Atomic service API**: This API can be used in atomic services since API version 12. 276 277**System capability**: SystemCapability.ArkUI.ArkUI.Full 278 279| Name | Type|Read-Only|Optional| Description | 280| ------ | ---- |------|------| ---------------- | 281| start | T |No|No| 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.| 282| end | T | No|No|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.| 283| top | T | No|No|Top edge.| 284| bottom | T | No|No|Bottom edge.| 285 286> **NOTE** 287> 288>- The custom layout does not support the LazyForEach syntax. 289>- 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. 290>- The size parameters of the parent component (custom component), except **aspectRatio**, are at a lower priority than those specified by **onMeasureSize**. 291>- 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. 292>- When using the custom layout method, you must call **onMeasureSize** and **onPlaceChildren** at the same time for the layout to display properly. 293 294## onLayout<sup>(deprecated)</sup> 295 296onLayout?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 297 298Invoked 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. 299 300This API is supported since API version 9 and deprecated since API version 10. You are advised to use [onPlaceChildren](#onplacechildren10) instead. 301 302**Widget capability**: This API can be used in ArkTS widgets since API version 9. 303 304**System capability**: SystemCapability.ArkUI.ArkUI.Full 305 306**Parameters** 307 308| Name | Type | Mandatory|Description | 309|------------|------------------------------------------------------------|------|------------------| 310| children | Array<[LayoutChild](#layoutchilddeprecated)> | Yes | Child component layout information. | 311| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes |Size constraint of the parent component.| 312 313## onMeasure<sup>(deprecated)</sup> 314 315onMeasure?(children: Array<LayoutChild>, constraint: ConstraintSizeOptions): void 316 317Invoked when the custom component needs to determine its size. Through this callback the component receives its child component layout information and its own size constraints from the ArkUI framework. State variables should not be changed in this callback. 318 319This API is supported since API version 9 and deprecated since API version 10. You are advised to use [onMeasureSize](#onmeasuresize10) instead. 320 321**Widget capability**: This API can be used in ArkTS widgets since API version 9. 322 323**System capability**: SystemCapability.ArkUI.ArkUI.Full 324 325**Parameters** 326 327| Name | Type |Mandatory| Description | 328|------------|------------------------------------------------------------|------|------------------| 329| children | Array<[LayoutChild](#layoutchilddeprecated)> | Yes |Child component layout information. | 330| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes |Size constraint of the parent component.| 331 332## LayoutChild<sup>(deprecated)</sup> 333 334Child component layout information. 335 336This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 337 338**Widget capability**: This API can be used in ArkTS widgets since API version 9. 339 340**System capability**: SystemCapability.ArkUI.ArkUI.Full 341 342| Name | Type | Read-Only|Optional|Description | 343| ---------- | ------------------------------------------------------------ | ------|------|-------------------------------------- | 344| name | string | No|No|Name of the child component. | 345| id | string | No|No|ID of the child component. | 346| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | No|No|Constraint size of the child component. | 347| borderInfo | [LayoutBorderInfo](#layoutborderinfodeprecated) | No|No|Provides the border information of the child component. | 348| position | [Position](ts-types.md#position) | No|No|Position coordinates of the child component. | 349| measure | (childConstraint: [ConstraintSizeOptions](ts-types.md#constraintsizeoptions)) => void |No|No| Method called to apply the size constraint to the child component.| 350| layout | (LayoutInfo: [LayoutInfo](#layoutinfodeprecated)) => void | No|No|Method called to apply the specified position information to the child component.| 351 352## LayoutBorderInfo<sup>(deprecated)</sup> 353 354Provides the border information of the child component. 355 356This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 357 358**Widget capability**: This API can be used in ArkTS widgets since API version 9. 359 360**System capability**: SystemCapability.ArkUI.ArkUI.Full 361 362| Name | Type | Read-Only|Optional|Description | 363|-------------|--------------------------------------|------|------|-------------------------| 364| borderWidth | [EdgeWidths](ts-types.md#edgewidths9) | No|No|Edge widths in different directions of the component.| 365| margin | [Margin](ts-types.md#margin) | No|No|Margin values in different directions of the component. | 366| padding | [Padding](ts-types.md#padding) | No|No|Padding values in different directions of the component. | 367 368## LayoutInfo<sup>(deprecated)</sup> 369 370Provides the layout information of the child component. 371 372This API is supported since API version 9 and deprecated since API version 10. It is supported in ArkTS widgets. 373 374**Widget capability**: This API can be used in ArkTS widgets since API version 9. 375 376**System capability**: SystemCapability.ArkUI.ArkUI.Full 377 378| Name | Type | Read-Only|Optional|Description | 379| ---------- | ---------------------------------------------------------- | ------|------|---------------- | 380| position | [Position](ts-types.md#position) |No|No| Position coordinates of the child component.| 381| constraint | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | No|No|Constraint size of the child component.| 382 383 384## Example 385 386### Example 1: Implementing a Custom Layout 387This example demonstrates how to implement a custom layout. 388```ts 389// xxx.ets 390@Entry 391@Component 392struct Index { 393 build() { 394 Column() { 395 CustomLayout({ builder: ColumnChildren }) 396 } 397 } 398} 399 400@Builder 401function ColumnChildren() { 402 ForEach([1, 2, 3], (index: number) => { // LazyForEach is not supported. 403 Text('S' + index) 404 .fontSize(30) 405 .width(100) 406 .height(100) 407 .borderWidth(2) 408 .offset({ x: 10, y: 20 }) 409 }) 410} 411 412@Component 413struct CustomLayout { 414 @Builder 415 doNothingBuilder() { 416 }; 417 418 @BuilderParam builder: () => void = this.doNothingBuilder; 419 @State startSize: number = 100; 420 result: SizeResult = { 421 width: 0, 422 height: 0 423 }; 424 425 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 426 let startPos = 300; 427 children.forEach((child) => { 428 let pos = startPos - child.measureResult.height; 429 child.layout({ x: pos, y: pos }) 430 }) 431 } 432 433 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 434 let size = 100; 435 children.forEach((child) => { 436 let result: MeasureResult = child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 437 size += result.width / 2 438 ; 439 }) 440 this.result.width = 100; 441 this.result.height = 400; 442 return this.result; 443 } 444 445 build() { 446 this.builder() 447 } 448} 449``` 450 451 452 453### Example 2: Determining Whether to Participate in Layout Calculation 454This example shows how to determine whether a component participates in layout calculation based on its position. 455```ts 456// xxx.ets 457@Entry 458@Component 459struct Index { 460 build() { 461 Column() { 462 CustomLayout({ builder: ColumnChildren }) 463 } 464 .justifyContent(FlexAlign.Center) 465 .width("100%") 466 .height("100%") 467 } 468} 469 470@Builder 471function ColumnChildren() { 472 ForEach([1, 2, 3], (item: number, index: number) => { // LazyForEach is not supported. 473 Text('S' + item) 474 .fontSize(20) 475 .width(60 + 10 * index) 476 .height(100) 477 .borderWidth(2) 478 .margin({ left:10 }) 479 .padding(10) 480 }) 481} 482 483@Component 484struct CustomLayout { 485 // Lay out only one row, and hide child components that are too large for the available space. 486 @Builder 487 doNothingBuilder() { 488 }; 489 490 @BuilderParam builder: () => void = this.doNothingBuilder; 491 result: SizeResult = { 492 width: 0, 493 height: 0 494 }; 495 overFlowIndex: number = -1; 496 497 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 498 let currentX = 0; 499 let infinity = 100000; 500 if (this.overFlowIndex == -1) { 501 this.overFlowIndex = children.length; 502 } 503 for (let index = 0; index < children.length; ++index) { 504 let child = children[index]; 505 if (index >= this.overFlowIndex) { 506 // Hide any child component that extends beyond the area of its parent component by placing it in a distant position. 507 child.layout({x: infinity, y: 0}); 508 continue; 509 } 510 child.layout({ x: currentX, y: 0 }) 511 let margin = child.getMargin(); 512 currentX += child.measureResult.width + margin.start + margin.end; 513 } 514 } 515 516 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 517 let width = 0; 518 let height = 0; 519 this.overFlowIndex = -1; 520 // Assume that the component width cannot exceed 200 vp or the maximum constraint. 521 let maxWidth = Math.min(200, constraint.maxWidth as number); 522 for (let index = 0; index < children.length; ++index) { 523 let child = children[index]; 524 let childResult: MeasureResult = child.measure({ 525 minHeight: constraint.minHeight, 526 minWidth: constraint.minWidth, 527 maxWidth: constraint.maxWidth, 528 maxHeight: constraint.maxHeight 529 }) 530 let margin = child.getMargin(); 531 let newWidth = width + childResult.width + margin.start + margin.end; 532 if (newWidth > maxWidth) { 533 // Record the index of the component that should not be laid out. 534 this.overFlowIndex = index; 535 break; 536 } 537 // Accumulate the width and height of the parent component. 538 width = newWidth; 539 height = Math.max(height, childResult.height + margin.top + margin.bottom); 540 } 541 this.result.width = width; 542 this.result.height = height; 543 return this.result; 544 } 545 546 build() { 547 this.builder() 548 } 549} 550``` 551 552 553 554### Example 3: Obtaining the Child Component FrameNode and Setting Related Attributes 555This example shows how to obtain the [FrameNode](../js-apis-arkui-frameNode.md) of a child component using **uniqueId** and change its size and background color using the FrameNode API. 556```ts 557import { FrameNode, NodeController } from '@kit.ArkUI'; 558@Entry 559@Component 560struct Index { 561 build() { 562 Column() { 563 CustomLayout() 564 } 565 } 566} 567 568class MyNodeController extends NodeController { 569 private rootNode: FrameNode | null = null; 570 makeNode(uiContext: UIContext): FrameNode | null { 571 this.rootNode = new FrameNode(uiContext) 572 return this.rootNode 573 } 574} 575 576@Component 577struct CustomLayout { 578 @Builder 579 childrenBuilder() { 580 ForEach([1, 2, 3], (index: number) => { // LazyForEach is not supported. 581 NodeContainer(new MyNodeController()) 582 }) 583 }; 584 585 @BuilderParam builder: () => void = this.childrenBuilder; 586 result: SizeResult = { 587 width: 0, 588 height: 0 589 }; 590 591 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 592 let prev = 0; 593 children.forEach((child) => { 594 let pos = prev + 10; 595 prev = pos + child.measureResult.width 596 child.layout({ x: pos, y: 0 }) 597 }) 598 } 599 600 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 601 let size = 100; 602 children.forEach((child) => { 603 console.log("child uniqueId: ", child.uniqueId) 604 const uiContext = this.getUIContext() 605 if (uiContext) { 606 let node: FrameNode | null = uiContext.getFrameNodeByUniqueId(child.uniqueId) // Obtain the FrameNode of the NodeContainer component. 607 if (node) { 608 node.getChild(0)!.commonAttribute.width(100) 609 node.getChild(0)!.commonAttribute.height(100) 610 node.getChild(0)!.commonAttribute.backgroundColor(Color.Pink) // Change the size and background color of the FrameNode. 611 } 612 } 613 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 614 }) 615 this.result.width = 320; 616 this.result.height = 100; 617 return this.result; 618 } 619 620 build() { 621 this.builder() 622 } 623} 624``` 625 626 627### Example 4: Allowing the Child Component to Ignore Parent Component Size Constraints 628This example demonstrates how to use the **fixAtIdealSize** property of the [LayoutPolicy](ts-types.md#layoutpolicy15) object to allow the child component to ignore parent component size constraints. 629```ts 630@Entry 631@Component 632struct Index { 633 @Builder 634 ColumnChildrenText() { 635 Text("=====Text=====Text=====Text=====Text=====Text=====Text=====Text=====Text" ) 636 .fontSize(16).fontColor(Color.Black) 637 .borderWidth(2).backgroundColor("#fff8dc") 638 .width(LayoutPolicy.fixAtIdealSize) // Set the child component's width to be unrestricted by the parent component. 639 .height(LayoutPolicy.fixAtIdealSize) // Set the child component's height to be unrestricted by the parent component. 640 } 641 642 build() { 643 Column() { 644 Column() { 645 CustomLayoutText({ builder: this.ColumnChildrenText }) 646 .backgroundColor("#f0ffff").borderRadius(20).margin(10) 647 } 648 .width(300) 649 .height(150) 650 .margin(10) 651 .backgroundColor(Color.Pink) 652 } 653 .width(350) 654 .height(680) 655 .margin(20) 656 .alignItems(HorizontalAlign.Center) 657 } 658} 659 660@Component 661struct CustomLayoutText { 662 @Builder 663 doSomethingBuilder() { 664 }; 665 666 @BuilderParam 667 builder: () => void = this.doSomethingBuilder; 668 result: SizeResult = { 669 width: 0, 670 height: 0 671 }; 672 // The custom component implements custom layout. 673 onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Array<Layoutable>, constraint: ConstraintSizeOptions) { 674 let posY = 20; 675 children.forEach((child) => { 676 let posX = (selfLayoutInfo.width - child.measureResult.width) / 2; 677 child.layout({ x: posX, y: posY }) 678 posY += child.measureResult.height + 30; 679 }) 680 } 681 682 onMeasureSize(selfLayoutInfo: GeometryInfo, children: Array<Measurable>, constraint: ConstraintSizeOptions) { 683 children.forEach((child) => { 684 let result: MeasureResult = child.measure({ maxWidth: 335, maxHeight: 50 }) // Set constraints on the size of the child component of the custom component. 685 }) 686 this.result.width = 200; 687 this.result.height = 130; 688 return this.result; 689 } 690 691 build() { 692 this.builder() 693 } 694} 695``` 696 697 698### Example 5: Modifying the Layout Through layout 699This example shows how to modify a layout through **layout**. 700<!--deprecated_code_no_check--> 701```ts 702// xxx.ets 703@Entry 704@Component 705struct Index { 706 build() { 707 Column() { 708 CustomLayout() { 709 ForEach([1, 2, 3], (index: number) => { 710 Text('Sub' + index) 711 .fontSize(30) 712 .borderWidth(2) 713 }) 714 } 715 } 716 } 717} 718 719 720@Component 721struct CustomLayout { 722 @Builder 723 doNothingBuilder() { 724 }; 725 726 @BuilderParam builder: () => void = this.doNothingBuilder; 727 728 onLayout(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 729 let pos = 0; 730 children.forEach((child) => { 731 child.layout({ position: { x: pos, y: pos }, constraint: constraint }) 732 pos += 70; 733 }) 734 } 735 736 onMeasure(children: Array<LayoutChild>, constraint: ConstraintSizeOptions) { 737 let size = 100; 738 children.forEach((child) => { 739 child.measure({ minHeight: size, minWidth: size, maxWidth: size, maxHeight: size }) 740 size += 50; 741 }) 742 } 743 744 build() { 745 this.builder() 746 } 747} 748``` 749 750 751