BuilderNode
The BuilderNode module provides APIs for creating a BuilderNode – a custom node that can be used to mount native components. A BuilderNode can be used only as a leaf node. Whenever possible, avoid operating child nodes and their attributes under the root node through the root node's render node.
NOTE
The initial APIs of this module are supported since API version 11. Newly added APIs will be marked with a superscript to indicate their earliest API version.
BuilderNode is not available in DevEco Studio Previewer.
Modules to Import
import { BuilderNode, RenderOptions, NodeRenderType } from "@ohos.arkui.node";
NodeRenderType
Enumerates the node rendering types.
System capability: SystemCapability.ArkUI.ArkUI.Full
Name | Value | Description |
---|---|---|
RENDER_TYPE_DISPLAY | 0 | The node is displayed on the screen. |
RENDER_TYPE_TEXTURE | 1 | The node is exported as a texture. |
RenderOptions
Provides optional parameters for creating a BuilderNode.
System capability: SystemCapability.ArkUI.ArkUI.Full
Name | Type | Mandatory | Description |
---|---|---|---|
selfIdealSize | Size | No | Ideal size of the node. |
type | NodeRenderType | No | Rendering type of the node. |
surfaceId | string | No | Surface ID of the texture receiver. Generally, the texture receiver is an OH_NativeImage instance. |
BuilderNode
class BuilderNode<Args extends Object[]>
Implements a BuilderNode, which can create a component tree through the stateless UI method @Builder and hold the root node of the component tree. A BuilderNode cannot be defined as a state variable. The FrameNode held in the BuilderNode is only used to mount the BuilderNode to other FrameNodes as a child node. Undefined behavior may occur if you set attributes or perform operations on subnodes of the FrameNode held by the BuilderNode. Therefore, after you have obtained a RenderNode through the getFrameNode method of the BuilderNode and the getRenderNode method of the FrameNode, avoid setting the attributes or operating the subnodes through APIs of the RenderNode.
System capability: SystemCapability.ArkUI.ArkUI.Full
constructor
constructor(uiContext: UIContext, options?: RenderOptions)
Constructor for creating a BuilderNode. When the content generated by the BuilderNode is embedded in another RenderNode for display, that is, the RenderNode corresponding to the BuilderNode is mounted to another RenderNode for display, selfIdealSize in RenderOptions must be explicitly specified. If selfIdealSize is not set, the node in the builder follows the default parent component layout constraint [0, 0], which means that the size of the root node of the subtree in BuilderNode is [0, 0].
System capability: SystemCapability.ArkUI.ArkUI.Full
Name | Type | Mandatory | Description |
---|---|---|---|
uiContext | UIContext | Yes | UI context. For details about how to obtain it, see [Obtaining UI Context. |
options | RenderOptions | No | Parameters for creating a BuilderNode. |
build
build(builder: WrappedBuilder<Args>, arg?: Object): void
Creates a component tree based on the passed object and holds the root node of the component tree. The stateless UI method @Builder has at most one root node. Custom components are allowed. Yet, the custom components cannot use decorators, such as @Reusable, @Link, @Prop, @Provide, and @Consume, for state synchronization with the owning page.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
Name | Type | Mandatory | Description |
---|---|---|---|
builder | WrappedBuilder<Args> | Yes | Stateless UI method @Builder required for creating a component tree. |
arg | Object | No | Object, which is used as the input parameter of the builder. |
getFrameNode
getFrameNode(): FrameNode | null
Obtains the FrameNode in the BuilderNode. The FrameNode is generated only after the BuilderNode executes the build operation.
System capability: SystemCapability.ArkUI.ArkUI.Full
Return value
Type | Description |
---|---|
FrameNode | null | FrameNode object. If no such object is held by the BuilderNode instance, null is returned. |
Example 1
In this example, the BuilderNode is returned as the root node of the <NodeContainer>.
import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
import { UIContext } from '@ohos.arkui.UIContext';
class Params {
text: string = ""
constructor(text: string) {
this.text = text;
}
}
@Builder
function buildText(params: Params) {
Column() {
Text(params.text)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({bottom: 36})
}
}
class TextNodeController extends NodeController {
private textNode: BuilderNode<[Params]> | null = null;
private message: string = "DEFAULT";
constructor(message: string) {
super();
this.message = message;
}
makeNode(context: UIContext): FrameNode | null {
this.textNode = new BuilderNode(context);
this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
return this.textNode.getFrameNode();
}
}
@Entry
@Component
struct Index {
@State message: string = "hello"
build() {
Row() {
Column() {
NodeContainer(new TextNodeController(this.message))
.width('100%')
.height(100)
.backgroundColor('#FFF0F0F0')
}
.width('100%')
.height('100%')
}
.height('100%')
}
}
Example 2
This example mounts the RenderNode of the BuilderNode to another RenderNode.
import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
import { UIContext } from '@ohos.arkui.UIContext';
class Params {
text: string = ""
constructor(text: string) {
this.text = text;
}
}
@Builder
function buildText(params: Params) {
Column() {
Text(params.text)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 36 })
}
}
class TextNodeController extends NodeController {
private rootNode: FrameNode | null = null;
private textNode: BuilderNode<[Params]> | null = null;
private message: string = "DEFAULT";
constructor(message: string) {
super();
this.message = message;
}
makeNode(context: UIContext): FrameNode | null {
this.rootNode = new FrameNode(context);
this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } });
this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message));
const textRenderNode = this.textNode?.getFrameNode()?.getRenderNode();
const rootRenderNode = this.rootNode.getRenderNode();
if (rootRenderNode !== null) {
rootRenderNode.appendChild(textRenderNode);
}
return this.rootNode;
}
}
@Entry
@Component
struct Index {
@State message: string = "hello"
build() {
Row() {
Column() {
NodeContainer(new TextNodeController(this.message))
.width('100%')
.height(100)
.backgroundColor('#FFF0F0F0')
}
.width('100%')
.height('100%')
}
.height('100%')
}
}
update
update(arg: Object): void
Updates this BuilderNode based on the provided parameter, which is of the same type as the input parameter passed to the build API. To call this API on a custom component, the variable used in the component must be defined as the @Prop type.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
Name | Type | Mandatory | Description |
---|---|---|---|
arg | Object | Yes | Parameter used to update the BuilderNode. It is of the same type as the parameter passed to the build API. |
Example
import { UIContext } from '@ohos.arkui.UIContext';
import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
class Params {
text: string = ""
constructor(text: string) {
this.text = text;
}
}
// Custom component
@Component
struct TextBuilder {
@Prop message: string = "TextBuilder";
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({bottom: 36})
.backgroundColor(Color.Gray)
}
}
}
}
@Builder
function buildText(params: Params) {
Column() {
Text(params.text)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 36 })
TextBuilder({message: params.text}) //Custom component
}
}
class TextNodeController extends NodeController {
private rootNode: FrameNode | null = null;
private textNode: BuilderNode<[Params]> | null = null;
private message: string = "";
constructor(message: string) {
super()
this.message = message
}
makeNode(context: UIContext): FrameNode | null {
this.textNode = new BuilderNode(context);
this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
return this.textNode.getFrameNode();
}
update(message: string) {
if (this.textNode !== null) {
this.textNode.update(new Params(message));
}
}
}
@Entry
@Component
struct Index {
@State message: string = "hello"
private textNodeController: TextNodeController = new TextNodeController(this.message);
private count = 0;
build() {
Row() {
Column() {
NodeContainer(this.textNodeController)
.width('100%')
.height(100)
.backgroundColor('#FFF0F0F0')
Button('Update')
.onClick(() => {
this.count += 1;
const message = "Update " + this.count.toString();
this.textNodeController.update(message);
})
}
.width('100%')
.height('100%')
}
.height('100%')
}
}
postTouchEvent
postTouchEvent(event: TouchEvent): boolean
Dispatches an event to the FrameNode created by this BuilderNode.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
Name | Type | Mandatory | Description |
---|---|---|---|
event | TouchEvent | Yes | Touch event. |
Return value
Type | Description |
---|---|
boolean | Whether the event is successfully dispatched. |
Example
import { UIContext } from '@ohos.arkui.UIContext';
import { NodeController, BuilderNode, FrameNode } from '@ohos.arkui.node';
class Params {
text: string = "this is a text"
}
@Builder
function ButtonBuilder(params: Params) {
Column() {
Button(`button ` + params.text)
.borderWidth(2)
.backgroundColor(Color.Orange)
.width("100%")
.height("100%")
.gesture(
TapGesture()
.onAction((event: GestureEvent) => {
console.log("TapGesture");
})
)
}
.width(500)
.height(300)
.backgroundColor(Color.Gray)
}
class MyNodeController extends NodeController {
private rootNode: BuilderNode<[Params]> | null = null;
private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(ButtonBuilder);
makeNode(uiContext: UIContext): FrameNode | null {
this.rootNode = new BuilderNode(uiContext);
this.rootNode.build(this.wrapBuilder, { text: "this is a string" })
return this.rootNode.getFrameNode();
}
postTouchEvent(touchEvent: TouchEvent): void {
if(this.rootNode == null){
return;
}
let result = this.rootNode.postTouchEvent(touchEvent);
console.log("result " + result);
}
}
@Entry
@Component
struct MyComponent {
private nodeController: MyNodeController = new MyNodeController();
build() {
Column() {
NodeContainer(this.nodeController)
.height(300)
.width(500)
Column()
.width(500)
.height(300)
.backgroundColor(Color.Pink)
.onTouch((event) => {
if(event != undefined){
this.nodeController.postTouchEvent(event);
}
})
}
}
}