Node
- 1、Node简介
- 2、FrameNode
-
- 2.1、创建和删除节点
- 2.2、对FrameNode的增删改
- 2.3、 FramNode的查询功能
- 3、demo源码
- 4、总结
- 5、参考资料
1、Node简介
在HarmonyOS(63) ArkUI 自定义占位组件NodeContainer介绍了自定义节点复用的原理(阅读本本篇博文之前,建议先读读这个),在NodeController里有有个makeNode
方法:
class MyNodeController extends NodeController {
private buttonNode: BuilderNode<[Params]> | null = null;
//绑定buttonBuilder
private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder);
//当实例绑定的NodeContainer创建的时候进行回调。回调方法将返回一个节点,将该节点挂载至NodeContainer。
//或者可以通过NodeController的rebuild()方法进行回调的触发。
makeNode(uiContext: UIContext): FrameNode {
if (this.buttonNode == null) {
//关于BuilderNode下文有所说明
this.buttonNode = new BuilderNode(uiContext);
this.buttonNode.build(this.wrapBuilder, {
text: "This is a Button" })
}
//返回FrameNode对象,返回的节点将被挂载至NodeContainer的占位节点上。若返回null对象,将清空对应NodeContainer的子节点。
return this.buttonNode!.getFrameNode()!;
}
}
在make方法里有两个核心概念:FrameNode、BuilderNode,今天这篇博文就来学习FrameNode。
自定义节点的挂载和显示需要依赖自定义占位节点。现有的自定义节点包括FrameNode、RenderNode、BuilderNode三类对象。FrameNode表示了单个的自定义组件节点(可以对比Android的View),RenderNode表示更加轻量级的渲染节点,BuilderNode对象提供了能够创建、更新原生组件以及组件树的能力。
2、FrameNode
FrameNode表示组件树的实体节点,配合自定义占位容器组件NodeContainer等,在占位容器内挂载一棵自定义的节点树,并对这个节点树中的节点进行动态的增加、修改、删除等操作。基础的FrameNode可以设置通用属性、设置事件回调,并提供完整的自定义能力,包括自定义测量、布局以及绘,具体可以分为两大类能力:完全自定义节点的能力以及原生组件节点代理的能力,可以类比Android
的View/ViewGroup
来理解FrameNode,可以通过FrameNode](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-user-defined-arktsnode-framenode-V5)实现类似Android
自定义View
的功能,。
-
完全自定义节点:提供完整的自定义能力,包括自定义测量、布局以及绘制,支持节点的动态增、删,设置通用属性,设置事件回调。适用于不自带渲染引擎,需要依赖系统的布局、事件、动画、渲染等能力的场景。
-
原生组件代理节点:提供原生组件的代理能力,提供遍历节点树的能力,通过组件树上的FrameNode可以遍历整个组件树,并通过节点访问组件的信息或者注册额外的事件监听回调,代理节点可以用于需要遍历整个UI的树形结构,并支持获取原生组件节点的具体信息或者额外注册组件的事件监听回调。适用于结合无感监听的接口实现打点、广告SDK、中台DFX等业务。
2.1、创建和删除节点
FrameNode提供了节点创建和删除的能力。可以通过FrameNode的构造函数创建自定义FrameNode节点,通过构造函数创建的节点对应一个实体的节点。同时,可以通过FrameNode中的dispose
接口来实现与实体节点的绑定关系的解除。
示例片段如下,全部代码传送门,文章后面也会有全部代码:
public buttonNode: BuilderNode<[Params]> | null = null;
public frameNode: FrameNode | null = null;
public rootNode: FrameNode | null = null;
makeNode(uiContext: UIContext): FrameNode | null {
this.uiContext = uiContext;
if (this.rootNode == null) {
this.rootNode = new FrameNode(uiContext);
this.rootNode.commonAttribute
.width("50%")//占屏幕宽度的一半
.height(100)
.borderWidth(1)
.backgroundColor(Color.Gray)
}
if (this.frameNode == null) {
//粉色矩形
this.frameNode = new FrameNode(uiContext);
this.frameNode.commonAttribute
.width("100%")
.height(50)//高度是rootNode的一半
.borderWidth(1)
.position({
x: 200, y: 0 })//位置信息
.backgroundColor(Color.Pink);
this.rootNode.appendChild(this.frameNode);
}
//生成两个button,一个是橘黄色的button,一个是粉色的button
if (this.buttonNode == null) {
this.buttonNode = new BuilderNode<[Params]>(uiContext);
this.buttonNode.build(this.wrapBuilder, {
text: "This is a Button" })
this.rootNode.appendChild(this.buttonNode.getFrameNode())
}
return this.rootNode;
}
上面代码告诉我们可以通过两种方式获取FrameNode:
1、直接new FrameNode
创建一个FrameNode。
2、通过BuilderNode对象的getFrameNode
方法获取FrameNode
上面代码创建了三个FrameNode:rootNode、frameNode、buttonNode
最终运行效果如下:
我们可以通过如下方法对rootNode、frameNode、buttonNode
进行正删改查功能
2.2、对FrameNode的增删改
为了测试FrameNode的增删改,定义了如下方法:
//该方法在MyNodeController类中
operationFrameNodeWithFrameNode(frameNode: FrameNode | undefined | null) {
if (frameNode) {
console.log(TEST_TAG + " get ArkTSNode success.")
//调用isModifiable方法判断是否FrameNode可以修改
console.log(TEST_TAG + " check rootNode whether is modifiable " + frameNode.isModifiable());
}
if (this.uiContext) {
//创建黑色方块的FrameNode
let frameNode1 = new FrameNode(this.uiContext);
//创建橘色方块的FrameNode
let frameNode2 = new FrameNode(this.uiContext);
//设置位置信息
frameNode1.commonAttribute.size({
width: 50, height: 50 })
.backgroundColor(Color.Black)
.position({
x: 50, y: 60 })
frameNode2.commonAttribute.size({
width: 50, height: 50 })
.backgroundColor(Color.Orange)
.position({
x: 120, y: 60 })
try {
//插入节点
frameNode?.appendChild(frameNode1)