1# \@Builder Decorator: Custom Builder Function 2 3ArkUI provides the \@Builder decorator that is a lightweight UI element reuse mechanism. This custom component has a fixed internal UI structure and passes the data only to the user. You can abstract reused UI elements into a method and call the method in the **build** method. 4 5For simplicity, here we refer to an \@Builder decorated function also as a custom builder function. 6 7 8> **NOTE** 9> 10> This decorator can be used in ArkTS widgets since API version 9. 11> 12> This decorator can be used in atomic services since API version 11. 13 14 15## Rules of Use 16 17### Private Custom Builder Function 18 19Syntax: 20 21```ts 22@Builder MyBuilderFunction() {} 23``` 24 25Usage: 26 27```ts 28this.MyBuilderFunction() 29``` 30 31- You can define one or more @Builder decorated methods in a custom component. Such a method is considered as a private, special type of member function of the component. 32 33- Private custom builder functions can be called in custom components, **build()**, and other custom builder functions. 34 35- Inside the custom builder function body, **this** refers to the owning component. Component state variables are accessible from within the custom builder function implementation. Using **this** to access the custom components' state variables is recommended over parameter passing. 36 37 38### Global Custom Builder Function 39 40Syntax: 41 42```ts 43@Builder function MyGlobalBuilderFunction() { ... } 44``` 45 46Usage: 47 48```ts 49MyGlobalBuilderFunction() 50``` 51 52- Use of a global custom builder function is recommended if no own state is involved. 53 54- Global custom builder functions can be called in **build()** and other custom builder functions. 55 56 57## Parameter Passing Rules 58 59For custom builder functions, parameters can be passed [by value](#by-value-parameter-passing) and [by reference](#by-reference-parameter-passing). Both of them must comply with the following rules: 60 61- The parameter type must be the same as the declared parameter type. The **undefined** or **null** constants as well as expressions evaluating to these values are not allowed. 62 63- All parameters must be immutable inside the custom builder function. 64 65- The custom builder function body follows the same [syntax rules](arkts-create-custom-components.md#build-function) as **build()**. 66 67- Parameters are passed by value in all cases except when only one parameter is passed in and the parameter needs to be directly passed to the object literal. 68 69 70### By-Reference Parameter Passing 71 72In by-reference parameter passing, state variables can be passed, and the change of these state variables causes the UI re-rendering in the \@Builder decorated method. 73 74```ts 75class Tmp { 76 paramA1: string = '' 77} 78 79@Builder function overBuilder(params: Tmp) { 80 Row() { 81 Text(`UseStateVarByReference: ${params.paramA1} `) 82 } 83} 84@Entry 85@Component 86struct Parent { 87 @State label: string = 'Hello'; 88 build() { 89 Column() { 90 // When the overBuilder component is called in the parent component, 91 // pass this.label to the overBuilder component by reference. 92 overBuilder({ paramA1: this.label }) 93 Button('Click me').onClick(() => { 94 // After you click "Click me", the UI text changes from "Hello" to "ArkUI". 95 this.label = 'ArkUI'; 96 }) 97 } 98 } 99} 100``` 101 102When parameters are passed by reference, if a custom component is called within the \@Builder method, ArkUI provides [$$](arkts-two-way-sync.md) as the paradigm for passing parameters by reference. 103 104```ts 105class Tmp { 106 paramA1: string = '' 107} 108 109@Builder function overBuilder($$: Tmp) { 110 Row() { 111 Column() { 112 Text(`overBuilder===${$$.paramA1}`) 113 HelloComponent({message: $$.paramA1}) 114 } 115 } 116} 117 118@Component 119struct HelloComponent { 120 @Prop message: string; 121 122 build() { 123 Row() { 124 Text(`HelloComponent===${this.message}`) 125 } 126 } 127} 128 129@Entry 130@Component 131struct Parent { 132 @State label: string = 'Hello'; 133 build() { 134 Column() { 135 // When the overBuilder component is called in the parent component, 136 // pass this.label to the overBuilder component by reference. 137 overBuilder({paramA1: this.label}) 138 Button('Click me').onClick(() => { 139 // After you click "Click me", the UI text changes from "Hello" to "ArkUI". 140 this.label = 'ArkUI'; 141 }) 142 } 143 } 144} 145``` 146 147### By-Value Parameter Passing 148 149By default, parameters in the \@Builder decorated functions are passed by value. In this case, when the passed parameter is a state variable, the change of the state variable does not cause UI re-rendering in the \@Builder decorated function. Therefore, when passing state variables, you are advised to use [by-reference parameter passing](#by-reference-parameter-passing). 150 151```ts 152@Builder function overBuilder(paramA1: string) { 153 Row() { 154 Text(`UseStateVarByValue: ${paramA1} `) 155 } 156} 157@Entry 158@Component 159struct Parent { 160 @State label: string = 'Hello'; 161 build() { 162 Column() { 163 overBuilder(this.label) 164 } 165 } 166} 167``` 168 169In the way of passing parameters by value, the @ObservedV2 and @Trace decorators can be used together in the @ComponentV2 decorated custom component to re-render the UI. 170 171[Positive Example] 172 173In @ComponentV2, only the @ObservedV2 decorated **ParamTmp** class and the @Trace decorated **count** property can trigger the UI re-render. 174 175```ts 176@ObservedV2 177class ParamTmp { 178 @Trace count : number = 0; 179} 180 181@Builder 182function renderText(param: ParamTmp) { 183 Column() { 184 Text(`param : ${param.count}`) 185 .fontSize(20) 186 .fontWeight(FontWeight.Bold) 187 } 188} 189 190@Builder 191function renderMap(paramMap: Map<string,number>) { 192 Text(`paramMap : ${paramMap.get('name')}`) 193 .fontSize(20) 194 .fontWeight(FontWeight.Bold) 195} 196 197@Builder 198function renderSet(paramSet: Set<number>) { 199 Text(`paramSet : ${paramSet.size}`) 200 .fontSize(20) 201 .fontWeight(FontWeight.Bold) 202} 203 204@Builder 205function renderNumberArr(paramNumArr: number[]) { 206 Text(`paramNumArr : ${paramNumArr[0]}`) 207 .fontSize(20) 208 .fontWeight(FontWeight.Bold) 209} 210 211@Entry 212@ComponentV2 213struct PageBuilder { 214 @Local builderParams: ParamTmp = new ParamTmp(); 215 @Local map_value: Map<string,number> = new Map(); 216 @Local set_value: Set<number> = new Set([0]); 217 @Local numArr_value: number[] = [0]; 218 private progressTimer: number = -1; 219 220 aboutToAppear(): void { 221 this.progressTimer = setInterval(() => { 222 if (this.builderParams.count < 100) { 223 this.builderParams.count += 5; 224 this.map_value.set('name', this.builderParams.count); 225 this.set_value.add(this.builderParams.count); 226 this.numArr_value[0] = this.builderParams.count; 227 } else { 228 clearInterval(this.progressTimer) 229 } 230 }, 500); 231 } 232 233 @Builder 234 localBuilder() { 235 Column() { 236 Text(`localBuilder : ${this.builderParams.count}`) 237 .fontSize(20) 238 .fontWeight(FontWeight.Bold) 239 } 240 } 241 242 build() { 243 Column() { 244 this.localBuilder() 245 Text(`builderParams :${this.builderParams.count}`) 246 .fontSize(20) 247 .fontWeight(FontWeight.Bold) 248 renderText(this.builderParams) 249 renderText({ count: this.builderParams.count }) 250 renderMap(this.map_value) 251 renderSet(this.set_value) 252 renderNumberArr(this.numArr_value) 253 } 254 .width('100%') 255 .height('100%') 256 } 257} 258``` 259 260[Negative Example] 261 262In the @ComponentV2 decorated custom component, the use of simple data types cannot trigger UI re-render. 263 264```ts 265@ObservedV2 266class ParamTmp { 267 @Trace count : number = 0; 268} 269 270@Builder 271function renderNumber(paramNum: number) { 272 Text(`paramNum : ${paramNum}`) 273 .fontSize(30) 274 .fontWeight(FontWeight.Bold) 275} 276 277@Entry 278@ComponentV2 279struct PageBuilder { 280 @Local class_value: ParamTmp = new ParamTmp(); 281 // Using simple data type cannot trigger UI re-render 282 @Local num_value: number = 0; 283 private progressTimer: number = -1; 284 285 aboutToAppear(): void { 286 this.progressTimer = setInterval(() => { 287 if (this.class_value.count < 100) { 288 this.class_value.count += 5; 289 this.num_value += 5; 290 } else { 291 clearInterval(this.progressTimer) 292 } 293 }, 500); 294 } 295 296 build() { 297 Column() { 298 renderNumber(this.num_value) 299 } 300 .width('100%') 301 .height('100%') 302 .padding(50) 303 } 304} 305``` 306 307## Constraints 308 3091. Parameter values cannot be changed in \@Builder decorated functions. Otherwise, the framework throws a runtime error. You can change the parameters in the \@Builder decorated custom components. 310 311```ts 312interface Temp { 313 paramA: string; 314} 315 316@Builder function overBuilder($$: Temp) { 317 Row() { 318 Column() { 319 Button(`overBuilder === ${$$.paramA}`) 320 .onClick(() => { 321 // Incorrect format. Parameter values cannot be changed in the function decorated by @Builder. 322 $$.paramA = 'Yes'; 323 }) 324 } 325 } 326} 327 328@Entry 329@Component 330struct Parent { 331 @State label: string = 'Hello'; 332 333 build() { 334 Column() { 335 overBuilder({paramA: this.label}) 336 Button('click me') 337 .onClick(() => { 338 this.label = 'ArkUI'; 339 }) 340 } 341 } 342} 343``` 344 3452. The \@Builder triggers dynamic UI rendering for only when parameters are passed in by reference. Only one parameter can be passed. 346 3473. If the \@Builder passes in two or more parameters, dynamic UI rendering is not triggered. 348 3494. If the \@Builder passes in parameters by value and by reference, dynamic UI rendering is not triggered. 350 3515. \@Builder parameters must be passed in one by one in the form of object literals to trigger dynamic UI rendering. 352 353 354## Use Scenarios 355 356### Using Custom Builder Function in Custom Component 357 358Create a private \@Builder method, call this method by using **this.builder()** in **Column**, and change the content of **builder_value** through the **aboutToAppear** lifecycle function and Button click event to dynamically render the UI. 359 360```ts 361@Entry 362@Component 363struct PrivateBuilder { 364 @State builder_value: string = 'Hello'; 365 366 @Builder builder() { 367 Column(){ 368 Text(this.builder_value) 369 .fontSize(30) 370 .fontWeight(FontWeight.Bold) 371 } 372 } 373 374 aboutToAppear(): void { 375 setTimeout(() => { 376 this.builder_value = 'Hello World'; 377 },3000) 378 } 379 380 build() { 381 Row() { 382 Column() { 383 Text(this.builder_value) 384 .fontSize(30) 385 .fontWeight(FontWeight.Bold) 386 this.builder() 387 Button('Click to change builder_value') 388 .onClick(() => { 389 this.builder_value = 'builder_value clicked' 390 }) 391 } 392 } 393 } 394} 395``` 396 397### Using Global Custom Builder Function 398 399Create a global \@Builder method and call this method by using **overBuilder()** in **Column**. Pass the simple type or complex type parameters in the form of object literals, value changes will trigger UI re-rendering. 400 401```ts 402class ChildTmp { 403 val: number = 1; 404} 405 406class Tmp { 407 str_value: string = 'Hello'; 408 num_value: number = 0; 409 tmp_value: ChildTmp = new ChildTmp(); 410 arrayTmp_value: Array<ChildTmp> = []; 411} 412 413@Builder function overBuilder(param: Tmp) { 414 Column() { 415 Text(`str_value: ${param.str_value}`) 416 Text(`num_value: ${param.num_value}`) 417 Text(`tmp_value: ${param.tmp_value.val}`) 418 ForEach(param.arrayTmp_value, (item: ChildTmp) => { 419 Text(`arrayTmp_value: ${item.val}`) 420 }, (item: ChildTmp) => JSON.stringify(item)) 421 } 422} 423 424@Entry 425@Component 426struct Parent { 427 @State objParam: Tmp = new Tmp(); 428 build() { 429 Column() { 430 Text('Render the UI by calling the @Builder') 431 .fontSize(20) 432 overBuilder({str_value: this.objParam.str_value, num_value: this.objParam.num_value, 433 tmp_value: this.objParam.tmp_value, arrayTmp_value: this.objParam.arrayTmp_value}) 434 Line() 435 .width('100%') 436 .height(10) 437 .backgroundColor('#000000').margin(10) 438 Button('Click to change parameter').onClick(() => { 439 this.objParam.str_value = 'Hello World'; 440 this.objParam.num_value = 1; 441 this.objParam.tmp_value.val = 8; 442 const child_value: ChildTmp = { 443 val: 2 444 } 445 this.objParam.arrayTmp_value.push(child_value) 446 }) 447 } 448 } 449} 450``` 451 452### Changing the Variables Decorated by the Decorator Triggers UI Re-rendering 453 454In this case, the decorator feature is used. The change of the listening value triggers UI re-rendering and parameters are not passed through the \@Builder. 455 456```ts 457class Tmp { 458 str_value: string = 'Hello'; 459} 460 461@Entry 462@Component 463struct Parent { 464 @State objParam: Tmp = new Tmp(); 465 @State label: string = 'World'; 466 467 @Builder privateBuilder() { 468 Column() { 469 Text(`wrapBuilder str_value: ${this.objParam.str_value}`) 470 Text(`wrapBuilder num: ${this.label}`) 471 } 472 } 473 474 build() { 475 Column() { 476 Text('Render the UI by calling the @Builder') 477 .fontSize(20) 478 this.privateBuilder() 479 Line() 480 .width('100%') 481 .height(10) 482 .backgroundColor('#000000').margin(10) 483 Button('Click to change parameter').onClick(() => { 484 this.objParam.str_value = 'str_value Hello World'; 485 this.label = 'label Hello World' 486 }) 487 } 488 } 489} 490``` 491 492### Using the Global and Local @Builder to Pass in Parameters of the customBuilder Type 493 494```ts 495@Builder 496function overBuilder() { 497 Row() { 498 Text('Global Builder') 499 .fontSize(30) 500 .fontWeight(FontWeight.Bold) 501 } 502} 503 504@Entry 505@Component 506struct customBuilderDemo { 507 @State arr: number[] = [0, 1, 2, 3, 4]; 508 509 @Builder privateBuilder() { 510 Row() { 511 Text('Local Builder') 512 .fontSize(30) 513 .fontWeight(FontWeight.Bold) 514 } 515 } 516 517 build() { 518 Column() { 519 List({ space: 10 }) { 520 ForEach(this.arr, (item: number) => { 521 ListItem(){ 522 Text(`${item}`) 523 .width('100%') 524 .height(100) 525 .fontSize(16) 526 .textAlign(TextAlign.Center) 527 .borderRadius(10) 528 .backgroundColor(0xFFFFFF) 529 } 530 .swipeAction({ 531 start: { 532 builder: overBuilder() 533 }, 534 end: { 535 builder: () => { this.privateBuilder() } 536 } 537 }) 538 }, (item: string) => JSON.stringify(item)) 539 } 540 } 541 } 542} 543``` 544 545### Nesting of Multi-layer \@Builder Method 546 547Call the custom components or other methods within \@Builder method. ArkUI provides [$$](arkts-two-way-sync.md) as a paradigm for passing parameters by reference. 548 549```ts 550class Tmp { 551 paramA1: string = ''; 552} 553 554@Builder function parentBuilder($$: Tmp) { 555 Row() { 556 Column() { 557 Text(`parentBuilder===${$$.paramA1}`) 558 .fontSize(30) 559 .fontWeight(FontWeight.Bold) 560 HelloComponent({message: $$.paramA1}) 561 childBuilder({paramA1: $$.paramA1}) 562 } 563 } 564} 565 566@Component 567struct HelloComponent { 568 @Prop message: string = ''; 569 570 build() { 571 Row() { 572 Text(`HelloComponent===${this.message}`) 573 .fontSize(30) 574 .fontWeight(FontWeight.Bold) 575 } 576 } 577} 578 579@Builder 580function childBuilder($$: Tmp) { 581 Row() { 582 Column() { 583 Text(`childBuilder===${$$.paramA1}`) 584 .fontSize(30) 585 .fontWeight(FontWeight.Bold) 586 HelloChildComponent({message: $$.paramA1}) 587 grandsonBuilder({paramA1: $$.paramA1}) 588 } 589 } 590} 591 592@Component 593struct HelloChildComponent { 594 @Prop message: string = ''; 595 build() { 596 Row() { 597 Text(`HelloChildComponent===${this.message}`) 598 .fontSize(30) 599 .fontWeight(FontWeight.Bold) 600 } 601 } 602} 603 604@Builder function grandsonBuilder($$: Tmp) { 605 Row() { 606 Column() { 607 Text(`grandsonBuilder===${$$.paramA1}`) 608 .fontSize(30) 609 .fontWeight(FontWeight.Bold) 610 HelloGrandsonComponent({message: $$.paramA1}) 611 } 612 } 613} 614 615@Component 616struct HelloGrandsonComponent { 617 @Prop message: string; 618 build() { 619 Row() { 620 Text(`HelloGrandsonComponent===${this.message}`) 621 .fontSize(30) 622 .fontWeight(FontWeight.Bold) 623 } 624 } 625} 626 627@Entry 628@Component 629struct Parent { 630 @State label: string = 'Hello'; 631 build() { 632 Column() { 633 parentBuilder({paramA1: this.label}) 634 Button('Click me').onClick(() => { 635 this.label = 'ArkUI'; 636 }) 637 } 638 } 639} 640``` 641 642### Using \@Builder Functions Together with the Decorators in V2 643 644Call the global @Builder and local @Builder in the @ComponentV2 decorated custom component to change related variables, triggering UI re-renders. 645 646```ts 647@ObservedV2 648class Info { 649 @Trace name: string = ''; 650 @Trace age: number = 0; 651} 652 653@Builder 654function overBuilder(param: Info) { 655 Column() { 656 Text('Global @Builder name :${param.name}`) 657 .fontSize(30) 658 .fontWeight(FontWeight.Bold) 659 Text('Global @Builder age :${param.age}`) 660 .fontSize(30) 661 .fontWeight(FontWeight.Bold) 662 } 663} 664 665@ComponentV2 666struct ChildPage { 667 @Require @Param childInfo: Info; 668 build() { 669 overBuilder({name: this.childInfo.name, age: this.childInfo.age}) 670 } 671} 672 673@Entry 674@ComponentV2 675struct ParentPage { 676 info1: Info = { name: "Tom", age: 25 }; 677 @Local info2: Info = { name: "Tom", age: 25 }; 678 679 @Builder 680 privateBuilder() { 681 Column() { 682 Text('Local @Builder name :${this.info1.name}`) 683 .fontSize(30) 684 .fontWeight(FontWeight.Bold) 685 Text('Local @Builder age :${this.info1.age}`) 686 .fontSize(30) 687 .fontWeight(FontWeight.Bold) 688 } 689 } 690 691 build() { 692 Column() { 693 Text(`info1: ${this.info1.name} ${this.info1.age}`) // Text1 694 .fontSize(30) 695 .fontWeight(FontWeight.Bold) 696 this.privateBuilder() // Call the local @Builder. 697 Line() 698 .width('100%') 699 .height(10) 700 .backgroundColor('#000000').margin(10) 701 Text(`info2: ${this.info2.name} ${this.info2.age}`) // Text2 702 .fontSize(30) 703 .fontWeight(FontWeight.Bold) 704 overBuilder({ name: this.info2.name, age: this.info2.age}) // Call the global @Builder. 705 Line() 706 .width('100%') 707 .height(10) 708 .backgroundColor('#000000').margin(10) 709 Text(`info1: ${this.info1.name} ${this.info1.age}`) // Text1 710 .fontSize(30) 711 .fontWeight(FontWeight.Bold) 712 ChildPage ({childInfo: this.info1}) // Call the custom component. 713 Line() 714 .width('100%') 715 .height(10) 716 .backgroundColor('#000000').margin(10) 717 Text(`info2: ${this.info2.name} ${this.info2.age}`) // Text2 718 .fontSize(30) 719 .fontWeight(FontWeight.Bold) 720 ChildPage ({childInfo: this.info2}) // Call the custom component. 721 Line() 722 .width('100%') 723 .height(10) 724 .backgroundColor('#000000').margin(10) 725 Button("change info1&info2") 726 .onClick(() => { 727 this.info1 = { name: "Cat", age: 18} // Text1 is not re-rendered because no decorator is used to listen for value changes. 728 this.info2 = { name: "Cat", age: 18} // Text2 is re-rendered because a decorator is used to listen for value changes. 729 }) 730 } 731 } 732} 733``` 734 735## FAQs 736 737### Two or More Parameters Are Used in the \@Builder 738 739When two or more parameters are used, the value change does not trigger the UI re-rendering even if the parameters are passed in the form of object literals. 740 741[Negative Example] 742 743```ts 744class GlobalTmp { 745 str_value: string = 'Hello'; 746} 747 748@Builder function overBuilder(param: GlobalTmp, num: number) { 749 Column() { 750 Text(`str_value: ${param.str_value}`) 751 Text(`num: ${num}`) 752 } 753} 754 755@Entry 756@Component 757struct Parent { 758 @State objParam: GlobalTmp = new GlobalTmp(); 759 @State num: number = 0; 760 build() { 761 Column() { 762 Text('Render the UI by calling the @Builder') 763 .fontSize(20) 764 // Two parameters are used, which is incorrect. 765 overBuilder({str_value: this.objParam.str_value}, this.num) 766 Line() 767 .width('100%') 768 .height(10) 769 .backgroundColor('#000000').margin(10) 770 Button('Click to change parameter').onClick(() => { 771 this.objParam.str_value = 'Hello World'; 772 this.num = 1; 773 }) 774 } 775 } 776} 777``` 778 779[Negative Example] 780 781```ts 782class GlobalTmp { 783 str_value: string = 'Hello'; 784} 785class SecondTmp { 786 num_value: number = 0; 787} 788@Builder function overBuilder(param: GlobalTmp, num: SecondTmp) { 789 Column() { 790 Text(`str_value: ${param.str_value}`) 791 Text(`num: ${num.num_value}`) 792 } 793} 794 795@Entry 796@Component 797struct Parent { 798 @State strParam: GlobalTmp = new GlobalTmp(); 799 @State numParam: SecondTmp = new SecondTmp(); 800 build() { 801 Column() { 802 Text('Render the UI by calling the @Builder') 803 .fontSize(20) 804 // Two parameters are used, which is incorrect. 805 overBuilder({str_value: this.strParam.str_value}, {num_value: this.numParam.num_value}) 806 Line() 807 .width('100%') 808 .height(10) 809 .backgroundColor('#000000').margin(10) 810 Button('Click to change parameter').onClick(() => { 811 this.strParam.str_value = 'Hello World'; 812 this.numParam.num_value = 1; 813 }) 814 } 815 } 816} 817``` 818 819Only one parameter can be used in the \@Builder. When one parameter is passed in the form of object literals, the value change triggers the UI re-rendering. 820 821[Positive Example] 822 823```ts 824class GlobalTmp { 825 str_value: string = 'Hello'; 826 num_value: number = 0; 827} 828@Builder function overBuilder(param: GlobalTmp) { 829 Column() { 830 Text(`str_value: ${param.str_value}`) 831 Text(`num: ${param.num_value}`) 832 } 833} 834 835@Entry 836@Component 837struct Parent { 838 @State objParam: GlobalTmp = new GlobalTmp(); 839 build() { 840 Column() { 841 Text('Render the UI by calling the @Builder') 842 .fontSize(20) 843 overBuilder({str_value: this.objParam.str_value, num_value: this.objParam.num_value}) 844 Line() 845 .width('100%') 846 .height(10) 847 .backgroundColor('#000000').margin(10) 848 Button('Click to change parameter').onClick(() => { 849 this.objParam.str_value = 'Hello World'; 850 this.objParam.num_value = 1; 851 }) 852 } 853 } 854} 855``` 856 857### Component Used in the \@Builder Function Is Not Added to a Root Node 858 859When using the **if** statement in the \@Builder function, if the created component is not added to the **Column** or **Row** root node, the component cannot be created. 860 861[Negative Example] 862 863```ts 864const showComponent: boolean = true; 865@Builder function OverlayNode() { 866 // The Text component is not created without adding it to the Column or Row root node. 867 if (showComponent) { 868 Text("This is overlayNode Blue page") 869 .fontSize(20) 870 .fontColor(Color.Blue) 871 .height(100) 872 .textAlign(TextAlign.End) 873 } else { 874 Text("This is overlayNode Red page") 875 .fontSize(20) 876 .fontColor(Color.Red) 877 } 878} 879 880@Entry 881@Component 882struct OverlayExample { 883 884 build() { 885 RelativeContainer() { 886 Text('Hello World') 887 .overlay(OverlayNode(), { align: Alignment.Center}) 888 } 889 .height('100%') 890 .width('100%') 891 } 892} 893``` 894 895[Positive Example] 896 897```ts 898const showComponent: boolean = true; 899@Builder function OverlayNode() { 900 Column() { 901 if (showComponent) { 902 Text("This is overlayNode Blue page") 903 .fontSize(20) 904 .fontColor(Color.Blue) 905 .height(100) 906 .textAlign(TextAlign.End) 907 } else { 908 Text("This is overlayNode Red page") 909 .fontSize(20) 910 .fontColor(Color.Red) 911 } 912 } 913} 914 915@Entry 916@Component 917struct OverlayExample { 918 919 build() { 920 RelativeContainer() { 921 Text('Hello World') 922 .overlay(OverlayNode(), { align: Alignment.Center}) 923 } 924 .height('100%') 925 .width('100%') 926 } 927} 928``` 929