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;//綁定buttonBuilderprivate 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,一個是粉色的buttonif (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) {//創建黑色方塊的FrameNodelet frameNode1 = new FrameNode(this.uiContext);//創建橘色方塊的FrameNodelet 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)