1e41f4b71Sopenharmony_ci# BuilderNode 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciThe [BuilderNode](../reference/apis-arkui/js-apis-arkui-builderNode.md) provides the capability to mount built-in components. It creates component trees with a stateless UI method, the [global custom builder function](../quick-start/arkts-builder.md#global-custom-builder-function), which is decorated by @Builder, and accesses the root [FrameNode](../reference/apis-arkui/js-apis-arkui-frameNode.md) through [getFrameNode](../reference/apis-arkui/js-apis-arkui-builderNode.md#getframenode). This node can be directly returned by [NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md) and mounted under the [NodeContainer](../reference/apis-arkui/arkui-ts/ts-basic-components-nodecontainer.md) node. It also enables embedding declarative component structures within **FrameNode** and [RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md) tree structures for mixed display capabilities. Additionally, the BuilderNode offers texture export functionality, with exported textures used for same-layer rendering in the [XComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md). 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThe BuilderNode enables the combination of ArkTS built-in component trees with custom nodes (such as FrameNodes and RenderNodes) for mixed display. It also allows built-in components to be embedded within third-party frameworks that use custom nodes. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciThe BuilderNode offers the capability to pre-create built-in components, enabling their initialization at customized times and dynamic mounting as needed in operations. This is particularly useful for reducing the initialization time of declarative components such as [Web](../reference/apis-arkweb/ts-basic-components-web.md) and [XComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md), which typically take longer to initialize. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ciA BuilderNode can be used only as a leaf node. If an update is required, you are advised to use the update APIs provided by the BuilderNode, rather than making modifications directly to the RenderNode obtained from it. 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci> **NOTE** 16e41f4b71Sopenharmony_ci> 17e41f4b71Sopenharmony_ci> - The BuilderNode only supports a single [global custom build function(../quick-start/arkts-builder.md#global-custom-builder-function) decorated by @Builder and wrapped by [wrapBuilder](../quick-start/arkts-wrapBuilder.md). 18e41f4b71Sopenharmony_ci> 19e41f4b71Sopenharmony_ci> - A newly created BuilderNode can only obtain a **FrameNode** object pointing to the root node through [getFrameNode](../reference/apis-arkui/js-apis-arkui-builderNode.md#getframenode) after [build](../reference/apis-arkui/js-apis-arkui-builderNode.md#build); otherwise, it returns **null**. 20e41f4b71Sopenharmony_ci> 21e41f4b71Sopenharmony_ci> - If the root node of the passed Builder is a syntactic node (such as **if/else** and **ForEach**), an additional FrameNode must be generated, which will be displayed as "BuilderProxyNode" in the node tree. 22e41f4b71Sopenharmony_ci> 23e41f4b71Sopenharmony_ci> - If BuilderNode mounts a node onto another FrameNode through **getFrameNode**, or mounts it as a child node onto a **NodeContainer**, the node uses the layout constraints of the parent component for layout. 24e41f4b71Sopenharmony_ci> 25e41f4b71Sopenharmony_ci> - If a BuilderNode's FrameNode mounts its node onto a RenderNode through [getRenderNode](../reference/apis-arkui/js-apis-arkui-frameNode.md#getrendernode), its size defaults to **0** since its FrameNode is not yet part of the tree. To display it properly, you must explicitly specify the layout constraint size through [selfIdeaSize](../reference/apis-arkui/js-apis-arkui-builderNode.md#renderoptions) in the constructor. 26e41f4b71Sopenharmony_ci> 27e41f4b71Sopenharmony_ci> - Pre-creation with the BuilderNode does not reduce the creation time of components. For the **Web** component, resources must be loaded in the kernel during creation, and pre-creation cannot reduce this time. However, it enables the kernel to preload resources, which can reduce the loading time when the component is used. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci## Creating a BuilderNode Object 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ciWhen creating a **BuilderNode** object, which is a template class, you must specify a type that matches the type of the [WrappedBuilder](../quick-start/arkts-wrapBuilder.md) used in the **build** method later on. Mismatches can cause compilation warnings and failures. 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci## Creating a Built-in Component Tree 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ciUse the **build** API of **BuilderNode** to create a built-in component tree. The tree is constructed based on the **WrappedBuilder** object passed in, and the root node of the component tree is retained. 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci> **NOTE** 38e41f4b71Sopenharmony_ci> 39e41f4b71Sopenharmony_ci> Stateless UI methods using the global @Builder can have at most one root node. 40e41f4b71Sopenharmony_ci> 41e41f4b71Sopenharmony_ci> The @Builder within the **build** method accepts only one input parameter. 42e41f4b71Sopenharmony_ci> 43e41f4b71Sopenharmony_ci> In scenarios where @Builder is nested within another @Builder in the **build** method, ensure that the parameters of the nested @Builder match the input parameters provided to the **build** method. 44e41f4b71Sopenharmony_ci> 45e41f4b71Sopenharmony_ci> For scenarios where @Builder is nested within another @Builder, if the parameter types do not match, you must include the BuilderOptions](../reference/apis-arkui/js-apis-arkui-builderNode.md#buildoptions12) field as a parameter for the [build](../reference/apis-arkui/js-apis-arkui-builderNode.md#build12) method. 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ciCreate offline nodes and built-in component trees, and use them in conjunction with FrameNodes. 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ciThe root node of the BuilderNode is directly used as the return value of [makeNode](../reference/apis-arkui/js-apis-arkui-nodeController.md#makenode) of [NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md). 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ci```ts 52e41f4b71Sopenharmony_ciimport { BuilderNode, FrameNode, NodeController, UIContext } from '@kit.ArkUI' 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ciclass Params { 55e41f4b71Sopenharmony_ci text: string = "" 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci constructor(text: string) { 58e41f4b71Sopenharmony_ci this.text = text; 59e41f4b71Sopenharmony_ci } 60e41f4b71Sopenharmony_ci} 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci@Builder 63e41f4b71Sopenharmony_cifunction buildText(params: Params) { 64e41f4b71Sopenharmony_ci Column() { 65e41f4b71Sopenharmony_ci Text(params.text) 66e41f4b71Sopenharmony_ci .fontSize(50) 67e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 68e41f4b71Sopenharmony_ci .margin({ bottom: 36 }) 69e41f4b71Sopenharmony_ci } 70e41f4b71Sopenharmony_ci} 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController { 73e41f4b71Sopenharmony_ci private textNode: BuilderNode<[Params]> | null = null; 74e41f4b71Sopenharmony_ci private message: string = "DEFAULT"; 75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ci constructor(message: string) { 77e41f4b71Sopenharmony_ci super(); 78e41f4b71Sopenharmony_ci this.message = message; 79e41f4b71Sopenharmony_ci } 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci makeNode(context: UIContext): FrameNode | null { 82e41f4b71Sopenharmony_ci this.textNode = new BuilderNode(context); 83e41f4b71Sopenharmony_ci this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)) 84e41f4b71Sopenharmony_ci return this.textNode.getFrameNode(); 85e41f4b71Sopenharmony_ci } 86e41f4b71Sopenharmony_ci} 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci@Entry 89e41f4b71Sopenharmony_ci@Component 90e41f4b71Sopenharmony_cistruct Index { 91e41f4b71Sopenharmony_ci @State message: string = "hello" 92e41f4b71Sopenharmony_ci 93e41f4b71Sopenharmony_ci build() { 94e41f4b71Sopenharmony_ci Row() { 95e41f4b71Sopenharmony_ci Column() { 96e41f4b71Sopenharmony_ci NodeContainer(new TextNodeController(this.message)) 97e41f4b71Sopenharmony_ci .width('100%') 98e41f4b71Sopenharmony_ci .height(100) 99e41f4b71Sopenharmony_ci .backgroundColor('#FFF0F0F0') 100e41f4b71Sopenharmony_ci } 101e41f4b71Sopenharmony_ci .width('100%') 102e41f4b71Sopenharmony_ci .height('100%') 103e41f4b71Sopenharmony_ci } 104e41f4b71Sopenharmony_ci .height('100%') 105e41f4b71Sopenharmony_ci } 106e41f4b71Sopenharmony_ci} 107e41f4b71Sopenharmony_ci``` 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ciWhen combining a BuilderNode with a RenderNode, note the following: 110e41f4b71Sopenharmony_ci 111e41f4b71Sopenharmony_ciIf you mount the RenderNode from the BuilderNode under another RenderNode, you must explicitly specify [selfIdeaSize](../reference/apis-arkui/js-apis-arkui-builderNode.md#renderoptions) as the layout constraint for the BuilderNode. This approach to mounting nodes is not recommended. 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci```ts 114e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext, RenderNode } from "@kit.ArkUI" 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_ciclass Params { 117e41f4b71Sopenharmony_ci text: string = "" 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci constructor(text: string) { 120e41f4b71Sopenharmony_ci this.text = text; 121e41f4b71Sopenharmony_ci } 122e41f4b71Sopenharmony_ci} 123e41f4b71Sopenharmony_ci 124e41f4b71Sopenharmony_ci@Builder 125e41f4b71Sopenharmony_cifunction buildText(params: Params) { 126e41f4b71Sopenharmony_ci Column() { 127e41f4b71Sopenharmony_ci Text(params.text) 128e41f4b71Sopenharmony_ci .fontSize(50) 129e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 130e41f4b71Sopenharmony_ci .margin({ bottom: 36 }) 131e41f4b71Sopenharmony_ci } 132e41f4b71Sopenharmony_ci} 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController { 135e41f4b71Sopenharmony_ci private rootNode: FrameNode | null = null; 136e41f4b71Sopenharmony_ci private textNode: BuilderNode<[Params]> | null = null; 137e41f4b71Sopenharmony_ci private message: string = "DEFAULT"; 138e41f4b71Sopenharmony_ci 139e41f4b71Sopenharmony_ci constructor(message: string) { 140e41f4b71Sopenharmony_ci super(); 141e41f4b71Sopenharmony_ci this.message = message; 142e41f4b71Sopenharmony_ci } 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ci makeNode(context: UIContext): FrameNode | null { 145e41f4b71Sopenharmony_ci this.rootNode = new FrameNode(context); 146e41f4b71Sopenharmony_ci let renderNode = new RenderNode(); 147e41f4b71Sopenharmony_ci renderNode.clipToFrame = false; 148e41f4b71Sopenharmony_ci this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } }); 149e41f4b71Sopenharmony_ci this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)); 150e41f4b71Sopenharmony_ci const textRenderNode = this.textNode?.getFrameNode()?.getRenderNode(); 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci const rootRenderNode = this.rootNode.getRenderNode(); 153e41f4b71Sopenharmony_ci if (rootRenderNode !== null) { 154e41f4b71Sopenharmony_ci rootRenderNode.appendChild(renderNode); 155e41f4b71Sopenharmony_ci renderNode.appendChild(textRenderNode); 156e41f4b71Sopenharmony_ci } 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci return this.rootNode; 159e41f4b71Sopenharmony_ci } 160e41f4b71Sopenharmony_ci} 161e41f4b71Sopenharmony_ci 162e41f4b71Sopenharmony_ci@Entry 163e41f4b71Sopenharmony_ci@Component 164e41f4b71Sopenharmony_cistruct Index { 165e41f4b71Sopenharmony_ci @State message: string = "hello" 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci build() { 168e41f4b71Sopenharmony_ci Row() { 169e41f4b71Sopenharmony_ci Column() { 170e41f4b71Sopenharmony_ci NodeContainer(new TextNodeController(this.message)) 171e41f4b71Sopenharmony_ci .width('100%') 172e41f4b71Sopenharmony_ci .height(100) 173e41f4b71Sopenharmony_ci .backgroundColor('#FFF0F0F0') 174e41f4b71Sopenharmony_ci } 175e41f4b71Sopenharmony_ci .width('100%') 176e41f4b71Sopenharmony_ci .height('100%') 177e41f4b71Sopenharmony_ci } 178e41f4b71Sopenharmony_ci .height('100%') 179e41f4b71Sopenharmony_ci } 180e41f4b71Sopenharmony_ci} 181e41f4b71Sopenharmony_ci``` 182e41f4b71Sopenharmony_ci 183e41f4b71Sopenharmony_ci## Updating the Built-in Component Tree 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ciCreate a built-in component tree using the **build** API of a **BuilderNode** object. The tree is constructed based on the **WrappedBuilder** object passed in, and the root node of the component tree is retained. 186e41f4b71Sopenharmony_ci 187e41f4b71Sopenharmony_ciCustom component updates follow the update mechanisms of [state management](../quick-start/arkts-state-management-overview.md). For custom components used directly in a **WrappedBuilder** object, their parent component is the **BuilderNode** object. Therefore, to update child components defined in the **WrappedBuilder** objects, you need to define the relevant state variables with the [@Prop](../quick-start/arkts-prop.md) or [@ObjectLink](../quick-start/arkts-observed-and-objectlink.md) decorator, in accordance with the specifications of state management and the needs of your application development. 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ciTo update nodes within a BuilderNode: 190e41f4b71Sopenharmony_ci 191e41f4b71Sopenharmony_ci- Use the **update** API to update individual nodes within the BuilderNode. 192e41f4b71Sopenharmony_ci- Use the [updateConfiguration](../reference/apis-arkui/js-apis-arkui-builderNode.md#updateconfiguration12) API to trigger a full update of all nodes within the BuilderNode. 193e41f4b71Sopenharmony_ci 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci 196e41f4b71Sopenharmony_ci```ts 197e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext } from "@kit.ArkUI" 198e41f4b71Sopenharmony_ci 199e41f4b71Sopenharmony_ciclass Params { 200e41f4b71Sopenharmony_ci text: string = "" 201e41f4b71Sopenharmony_ci constructor(text: string) { 202e41f4b71Sopenharmony_ci this.text = text; 203e41f4b71Sopenharmony_ci } 204e41f4b71Sopenharmony_ci} 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci// Custom component 207e41f4b71Sopenharmony_ci@Component 208e41f4b71Sopenharmony_cistruct TextBuilder { 209e41f4b71Sopenharmony_ci // The @Prop decorated attribute is the attribute to be updated in the custom component. It is a basic attribute. 210e41f4b71Sopenharmony_ci @Prop message: string = "TextBuilder"; 211e41f4b71Sopenharmony_ci 212e41f4b71Sopenharmony_ci build() { 213e41f4b71Sopenharmony_ci Row() { 214e41f4b71Sopenharmony_ci Column() { 215e41f4b71Sopenharmony_ci Text(this.message) 216e41f4b71Sopenharmony_ci .fontSize(50) 217e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 218e41f4b71Sopenharmony_ci .margin({ bottom: 36 }) 219e41f4b71Sopenharmony_ci .backgroundColor(Color.Gray) 220e41f4b71Sopenharmony_ci } 221e41f4b71Sopenharmony_ci } 222e41f4b71Sopenharmony_ci } 223e41f4b71Sopenharmony_ci} 224e41f4b71Sopenharmony_ci 225e41f4b71Sopenharmony_ci@Builder 226e41f4b71Sopenharmony_cifunction buildText(params: Params) { 227e41f4b71Sopenharmony_ci Column() { 228e41f4b71Sopenharmony_ci Text(params.text) 229e41f4b71Sopenharmony_ci .fontSize(50) 230e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 231e41f4b71Sopenharmony_ci .margin({ bottom: 36 }) 232e41f4b71Sopenharmony_ci TextBuilder({ message: params.text }) // Custom component 233e41f4b71Sopenharmony_ci } 234e41f4b71Sopenharmony_ci} 235e41f4b71Sopenharmony_ci 236e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController { 237e41f4b71Sopenharmony_ci private textNode: BuilderNode<[Params]> | null = null; 238e41f4b71Sopenharmony_ci private message: string = ""; 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci constructor(message: string) { 241e41f4b71Sopenharmony_ci super() 242e41f4b71Sopenharmony_ci this.message = message 243e41f4b71Sopenharmony_ci } 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci makeNode(context: UIContext): FrameNode | null { 246e41f4b71Sopenharmony_ci this.textNode = new BuilderNode(context); 247e41f4b71Sopenharmony_ci this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)) 248e41f4b71Sopenharmony_ci return this.textNode.getFrameNode(); 249e41f4b71Sopenharmony_ci } 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci update(message: string) { 252e41f4b71Sopenharmony_ci if (this.textNode !== null) { 253e41f4b71Sopenharmony_ci // Call update to perform an update. 254e41f4b71Sopenharmony_ci this.textNode.update(new Params(message)); 255e41f4b71Sopenharmony_ci } 256e41f4b71Sopenharmony_ci } 257e41f4b71Sopenharmony_ci} 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci@Entry 260e41f4b71Sopenharmony_ci@Component 261e41f4b71Sopenharmony_cistruct Index { 262e41f4b71Sopenharmony_ci @State message: string = "hello" 263e41f4b71Sopenharmony_ci private textNodeController: TextNodeController = new TextNodeController(this.message); 264e41f4b71Sopenharmony_ci private count = 0; 265e41f4b71Sopenharmony_ci 266e41f4b71Sopenharmony_ci build() { 267e41f4b71Sopenharmony_ci Row() { 268e41f4b71Sopenharmony_ci Column() { 269e41f4b71Sopenharmony_ci NodeContainer(this.textNodeController) 270e41f4b71Sopenharmony_ci .width('100%') 271e41f4b71Sopenharmony_ci .height(200) 272e41f4b71Sopenharmony_ci .backgroundColor('#FFF0F0F0') 273e41f4b71Sopenharmony_ci Button('Update') 274e41f4b71Sopenharmony_ci .onClick(() => { 275e41f4b71Sopenharmony_ci this.count += 1; 276e41f4b71Sopenharmony_ci const message = "Update " + this.count.toString(); 277e41f4b71Sopenharmony_ci this.textNodeController.update(message); 278e41f4b71Sopenharmony_ci }) 279e41f4b71Sopenharmony_ci } 280e41f4b71Sopenharmony_ci .width('100%') 281e41f4b71Sopenharmony_ci .height('100%') 282e41f4b71Sopenharmony_ci } 283e41f4b71Sopenharmony_ci .height('100%') 284e41f4b71Sopenharmony_ci } 285e41f4b71Sopenharmony_ci} 286e41f4b71Sopenharmony_ci``` 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci## Canceling the Reference to the Entity Node 289e41f4b71Sopenharmony_ci 290e41f4b71Sopenharmony_ciA **BuilderNode** object is mapped to a backend entity node, and its memory release is usually contingent on the disposal of the frontend object. To directly release the backend node object, you can call the [dispose](../reference/apis-arkui/js-apis-arkui-builderNode.md#dispose12) API to break the reference to the entity node. Once this is done, the frontend **BuilderNode** object will no longer affect the lifecycle of the entity node. 291e41f4b71Sopenharmony_ci 292e41f4b71Sopenharmony_ci> **NOTE** 293e41f4b71Sopenharmony_ci> 294e41f4b71Sopenharmony_ci> Calling **dispose** on a **BuilderNode** object breaks its reference to the backend entity node, and also simultaneously severs the references of its contained FrameNode and RenderNode to their respective entity nodes. 295e41f4b71Sopenharmony_ci 296e41f4b71Sopenharmony_ci## Injecting a Touch Event 297e41f4b71Sopenharmony_ci 298e41f4b71Sopenharmony_ciUse the [postTouchEvent](../reference/apis-arkui/js-apis-arkui-builderNode.md#posttouchevent) API in the BuilderNode to inject a [touch event](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) into the bound component for event simulation and forwarding. 299e41f4b71Sopenharmony_ci 300e41f4b71Sopenharmony_ciThe following example forwards a touch event from one **Column** component to another in the BuilderNode, so that when the lower **Column** component is touched, the upper **Column** component also receives the same touch event. The API returns **true** if the button's event is successfully recognized. 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ci```ts 303e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ciclass Params { 306e41f4b71Sopenharmony_ci text: string = "this is a text" 307e41f4b71Sopenharmony_ci} 308e41f4b71Sopenharmony_ci 309e41f4b71Sopenharmony_ci@Builder 310e41f4b71Sopenharmony_cifunction ButtonBuilder(params: Params) { 311e41f4b71Sopenharmony_ci Column() { 312e41f4b71Sopenharmony_ci Button(`button ` + params.text) 313e41f4b71Sopenharmony_ci .borderWidth(2) 314e41f4b71Sopenharmony_ci .backgroundColor(Color.Orange) 315e41f4b71Sopenharmony_ci .width("100%") 316e41f4b71Sopenharmony_ci .height("100%") 317e41f4b71Sopenharmony_ci .gesture( 318e41f4b71Sopenharmony_ci TapGesture() 319e41f4b71Sopenharmony_ci .onAction((event: GestureEvent) => { 320e41f4b71Sopenharmony_ci console.log("TapGesture"); 321e41f4b71Sopenharmony_ci }) 322e41f4b71Sopenharmony_ci ) 323e41f4b71Sopenharmony_ci } 324e41f4b71Sopenharmony_ci .width(500) 325e41f4b71Sopenharmony_ci .height(300) 326e41f4b71Sopenharmony_ci .backgroundColor(Color.Gray) 327e41f4b71Sopenharmony_ci} 328e41f4b71Sopenharmony_ci 329e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController { 330e41f4b71Sopenharmony_ci private rootNode: BuilderNode<[Params]> | null = null; 331e41f4b71Sopenharmony_ci private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(ButtonBuilder); 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci makeNode(uiContext: UIContext): FrameNode | null { 334e41f4b71Sopenharmony_ci this.rootNode = new BuilderNode(uiContext); 335e41f4b71Sopenharmony_ci this.rootNode.build(this.wrapBuilder, { text: "this is a string" }) 336e41f4b71Sopenharmony_ci return this.rootNode.getFrameNode(); 337e41f4b71Sopenharmony_ci } 338e41f4b71Sopenharmony_ci 339e41f4b71Sopenharmony_ci postTouchEvent(touchEvent: TouchEvent): void { 340e41f4b71Sopenharmony_ci if (this.rootNode == null) { 341e41f4b71Sopenharmony_ci return; 342e41f4b71Sopenharmony_ci } 343e41f4b71Sopenharmony_ci let result = this.rootNode.postTouchEvent(touchEvent); 344e41f4b71Sopenharmony_ci console.log("result " + result); 345e41f4b71Sopenharmony_ci } 346e41f4b71Sopenharmony_ci} 347e41f4b71Sopenharmony_ci 348e41f4b71Sopenharmony_ci@Entry 349e41f4b71Sopenharmony_ci@Component 350e41f4b71Sopenharmony_cistruct MyComponent { 351e41f4b71Sopenharmony_ci private nodeController: MyNodeController = new MyNodeController(); 352e41f4b71Sopenharmony_ci 353e41f4b71Sopenharmony_ci build() { 354e41f4b71Sopenharmony_ci Column() { 355e41f4b71Sopenharmony_ci NodeContainer(this.nodeController) 356e41f4b71Sopenharmony_ci .height(300) 357e41f4b71Sopenharmony_ci .width(500) 358e41f4b71Sopenharmony_ci Column() 359e41f4b71Sopenharmony_ci .width(500) 360e41f4b71Sopenharmony_ci .height(300) 361e41f4b71Sopenharmony_ci .backgroundColor(Color.Pink) 362e41f4b71Sopenharmony_ci .onTouch((event) => { 363e41f4b71Sopenharmony_ci if (event != undefined) { 364e41f4b71Sopenharmony_ci this.nodeController.postTouchEvent(event); 365e41f4b71Sopenharmony_ci } 366e41f4b71Sopenharmony_ci }) 367e41f4b71Sopenharmony_ci } 368e41f4b71Sopenharmony_ci } 369e41f4b71Sopenharmony_ci} 370e41f4b71Sopenharmony_ci``` 371e41f4b71Sopenharmony_ci<!--no_check-->