文档管理中心

查询和操作NDK节点

NDK提供一系列节点查询、遍历、操作能力,通过使用以下接口,开发者可以高效地访问和操控节点。

以下场景基于接入ArkTS页面章节,创建前置工程。

查询节点uniqueId及通过uniqueId获取节点信息

uniqueId是系统分配的唯一标识的节点Id。

从API version 20开始,使用OH_ArkUI_NodeUtils_GetNodeUniqueId接口,可以获取目标节点的uniqueId。使用OH_ArkUI_NodeUtils_GetNodeHandleByUniqueId接口,可以通过uniqueId获取目标节点的指针。

收起
自动换行
深色代码主题
复制
  1. const unsigned int VALUE_1 = 480;
  2. const unsigned int VALUE_2 = 300;
  3. const unsigned int VALUE_3 = 50;
  4. std::shared_ptr<ArkUIBaseNode> InquireUniqueId::GetNodeUniqueId()
  5. {
  6. ArkUI_NativeNodeAPI_1* nodeAPI = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
  7. ArkUI_NodeHandle testNode = nodeAPI->createNode(ARKUI_NODE_COLUMN);
  8. ArkUI_NumberValue value[] = {VALUE_1};
  9. ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
  10. value[0].f32 = VALUE_2;
  11. nodeAPI->setAttribute(testNode, NODE_WIDTH, &item);
  12. nodeAPI->setAttribute(testNode, NODE_HEIGHT, &item);
  13. struct IdList {
  14. int32_t id = -1;
  15. };
  16. static IdList idl;
  17. int32_t uid = -1;
  18. OH_ArkUI_NodeUtils_GetNodeUniqueId(testNode, &uid);
  19. idl.id = uid;
  20. auto button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
  21. value[0].f32 = VALUE_3;
  22. nodeAPI->setAttribute(button, NODE_WIDTH, &item);
  23. nodeAPI->setAttribute(button, NODE_HEIGHT, &item);
  24. nodeAPI->addChild(testNode, button);
  25. nodeAPI->registerNodeEvent(button, NODE_ON_CLICK, 1, &idl);
  26. OH_LOG_Print(LOG_APP, LOG_WARN, LOG_PRINT, "GetNodeUniqueId", "GetNodeHandleByUniqueId success1");
  27. nodeAPI->registerNodeEventReceiver([](ArkUI_NodeEvent *event) {
  28. auto targetId = OH_ArkUI_NodeEvent_GetTargetId(event);
  29. if (targetId == 1) {
  30. auto idl = (IdList *)OH_ArkUI_NodeEvent_GetUserData(event);
  31. ArkUI_NodeHandle Test_Column;
  32. auto ec = OH_ArkUI_NodeUtils_GetNodeHandleByUniqueId(idl->id, &Test_Column);
  33. if (ec == 0) {
  34. OH_LOG_Print(LOG_APP, LOG_WARN, LOG_PRINT, "GetNodeUniqueId", "GetNodeHandleByUniqueId success");
  35. }
  36. }
  37. });

通过用户id获取节点信息

使用OH_ArkUI_NodeUtils_GetAttachedNodeHandleById接口,可以通过用户设置的id获取目标节点的指针。

  1. ArkTS侧接入Native组件。

    收起
    自动换行
    深色代码主题
    复制
    1. import nativeNode from 'libentry.so';
    2. import { NodeContent } from '@kit.ArkUI';
    3. @Entry
    4. @Component
    5. struct GetNodeById {
    6. private rootSlot = new NodeContent();
    7. aboutToAppear(): void {
    8. nativeNode.createUserIdNode(this.rootSlot);
    9. }
    10. build() {
    11. Scroll() {
    12. Column({ space: 15 }) {
    13. Column() {
    14. ContentSlot(this.rootSlot)
    15. }
    16. }
    17. .width('100%')
    18. }.scrollBarColor(Color.Transparent)
    19. }
    20. }
  2. 新建GetNodeByIdExample.h文件,在其中创建Text节点并设置id属性,通过OH_ArkUI_NodeUtils_GetAttachedNodeHandleById接口拿到节点。

    收起
    自动换行
    深色代码主题
    复制
    1. // GetNodeByIdExample.h
    2. #ifndef MYAPPLICATION_GETNODEBYID_H
    3. #define MYAPPLICATION_GETNODEBYID_H
    4. #include "ArkUINode.h"
    5. #include <hilog/log.h>
    6. namespace NativeModule {
    7. std::shared_ptr<ArkUIBaseNode> CreateGetNodeByIdExample()
    8. {
    9. auto nodeAPI = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
    10. // 创建根节点Scroll
    11. ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_SCROLL);
    12. ArkUI_NumberValue length_value[] = {{.f32 = 480}};
    13. ArkUI_AttributeItem length_item = {length_value, sizeof(length_value) / sizeof(ArkUI_NumberValue)};
    14. nodeAPI->setAttribute(scroll, NODE_WIDTH, &length_item);
    15. ArkUI_NumberValue length_value1[] = {{.f32 = 650}};
    16. ArkUI_AttributeItem length_item1 = {length_value1, sizeof(length_value1) / sizeof(ArkUI_NumberValue)};
    17. nodeAPI->setAttribute(scroll, NODE_HEIGHT, &length_item1);
    18. ArkUI_AttributeItem scroll_id = {.string = "Scroll_CAPI"};
    19. nodeAPI->setAttribute(scroll, NODE_ID, &scroll_id);
    20. // 创建Column
    21. ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    22. ArkUI_NumberValue value[] = {480};
    23. ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    24. nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    25. ArkUI_NumberValue column_bc[] = {{.u32 = 0xFFF00BB}};
    26. ArkUI_AttributeItem column_item = {column_bc, 1};
    27. nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &column_item);
    28. ArkUI_AttributeItem column_id = {.string = "Column_CAPI"};
    29. nodeAPI->setAttribute(column, NODE_ID, &column_id);
    30. // 创建Text
    31. ArkUI_NodeHandle text0 = nodeAPI->createNode(ARKUI_NODE_TEXT);
    32. ArkUI_NumberValue text_width[] = {300};
    33. ArkUI_AttributeItem text_item0 = {text_width, sizeof(text_width) / sizeof(ArkUI_NumberValue)};
    34. nodeAPI->setAttribute(text0, NODE_WIDTH, &text_item0);
    35. ArkUI_NumberValue text_height[] = {50};
    36. ArkUI_AttributeItem text_item1 = {text_height, sizeof(text_height) / sizeof(ArkUI_NumberValue)};
    37. nodeAPI->setAttribute(text0, NODE_HEIGHT, &text_item1);
    38. ArkUI_AttributeItem text_item = {.string = "示例Text节点"};
    39. nodeAPI->setAttribute(text0, NODE_TEXT_CONTENT, &text_item);
    40. ArkUI_NumberValue margin[] = {10};
    41. ArkUI_AttributeItem item_margin = {margin, sizeof(margin) / sizeof(ArkUI_NumberValue)};
    42. nodeAPI->setAttribute(text0, NODE_MARGIN, &item_margin);
    43. ArkUI_AttributeItem text0_id = {.string = "Text0_CAPI"};
    44. nodeAPI->setAttribute(text0, NODE_ID, &text0_id);
    45. // 创建Row
    46. ArkUI_NodeHandle row0 = nodeAPI->createNode(ARKUI_NODE_ROW);
    47. ArkUI_NumberValue width_value[] = {{.f32=330}};
    48. ArkUI_AttributeItem width_item = {width_value, sizeof(width_value) / sizeof(ArkUI_NumberValue)};
    49. nodeAPI->setAttribute(row0, NODE_WIDTH, &width_item);
    50. nodeAPI->setAttribute(row0, NODE_HEIGHT, &text_item1);
    51. nodeAPI->setAttribute(row0, NODE_MARGIN, &item_margin);
    52. // 创建Button
    53. ArkUI_NodeHandle bt0 = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    54. ArkUI_NumberValue btn_width[] = {150};
    55. ArkUI_AttributeItem btn_item0 = {btn_width, sizeof(btn_width) / sizeof(ArkUI_NumberValue)};
    56. nodeAPI->setAttribute(bt0, NODE_WIDTH, &btn_item0);
    57. nodeAPI->setAttribute(bt0, NODE_HEIGHT, &text_item1);
    58. nodeAPI->setAttribute(bt0, NODE_MARGIN, &item_margin);
    59. ArkUI_AttributeItem bt0_item = {.string = "GetAttachedNodeHandleById"};
    60. nodeAPI->setAttribute(bt0, NODE_BUTTON_LABEL, &bt0_item);
    61. nodeAPI->registerNodeEvent(bt0, NODE_ON_CLICK, 0, text0);
    62. // 注册事件
    63. auto onClick = [](ArkUI_NodeEvent *event) {
    64. auto nodeAPI = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
    65. if (OH_ArkUI_NodeEvent_GetTargetId(event) == 0) { // GetAttachedNodeHandleById
    66. auto text0 = (ArkUI_NodeHandle)OH_ArkUI_NodeEvent_GetUserData(event);
    67. ArkUI_NodeHandle node = nullptr;
    68. auto res = OH_ArkUI_NodeUtils_GetAttachedNodeHandleById("Text0_CAPI", &node);
    69. if (res == ARKUI_ERROR_CODE_NO_ERROR && node == text0) {
    70. OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "GetNodeByIdExample", "get Text0_CAPI success");
    71. } else {
    72. OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "GetNodeByIdExample", "get Text0_CAPI failed");
    73. }
    74. }
    75. };
    76. nodeAPI->registerNodeEventReceiver(onClick);
    77. // 节点添加
    78. nodeAPI->addChild(scroll, column);
    79. nodeAPI->addChild(column, text0);
    80. nodeAPI->addChild(column, row0);
    81. nodeAPI->addChild(row0, bt0);
    82. return std::make_shared<ArkUINode>(scroll);
    83. }
    84. } // namespace NativeModule
    85. #endif // MYAPPLICATION_GETNODEBYID_H
  3. 在NativeEntry.cpp中,挂载Native节点。

    收起
    自动换行
    深色代码主题
    复制
    1. // NativeEntry.cpp
    2. #include <arkui/native_node_napi.h>
    3. #include <hilog/log.h>
    4. #include <js_native_api.h>
    5. #include "NativeEntry.h"
    6. #include "MoveToExample.h"
    7. #include "GetNodeByIdExample.h"
    8. namespace NativeModule {
    9. // ...
    10. static napi_value CreateNativeRoot(napi_env env, napi_callback_info info, const char *who, MakeNodeFn makeNodeFn)
    11. {
    12. size_t argc = 1;
    13. napi_value args[1] = {nullptr};
    14. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    15. // 获取NodeContent
    16. ArkUI_NodeContentHandle contentHandle;
    17. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    18. if (contentHandle == nullptr) {
    19. OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, K_LOG_DOMAIN,
    20. "%{public}s nodeContentHandle is null", who);
    21. return nullptr;
    22. }
    23. NativeEntry::GetInstance()->SetContentHandle(contentHandle);
    24. // 创建节点
    25. auto node = makeNodeFn();
    26. // 保持Native侧对象到管理类中,维护生命周期。
    27. NativeEntry::GetInstance()->SetRootNode(node);
    28. return nullptr;
    29. }
    30. napi_value DestroyNativeRoot(napi_env env, napi_callback_info info)
    31. {
    32. // 从管理类中释放Native侧对象。
    33. NativeEntry::GetInstance()->DisposeRootNode();
    34. return nullptr;
    35. }
    36. // ...
    37. } // namespace NativeModule
  4. 运行程序,点击按钮,打印节点获取成功信息。

移动节点

使用OH_ArkUI_NodeUtils_MoveTo接口,可以将Native节点移动到新的父节点下,从而按需改变节点树结构。

说明

当前仅支持以下类型的ArkUI_NodeType进行移动操作:ARKUI_NODE_STACK、ARKUI_NODE_XCOMPONENT、ARKUI_NODE_EMBEDDED_COMPONENT。对于其他类型的节点,移动操作不会生效。

  1. ArkTS侧接入Native组件。

    收起
    自动换行
    深色代码主题
    复制
    1. // MoveTo.ets
    2. import nativeNode from 'libentry.so';
    3. import { NodeContent } from '@kit.ArkUI';
    4. @Entry
    5. @Component
    6. struct MoveTo {
    7. private rootSlot = new NodeContent();
    8. aboutToAppear(): void {
    9. nativeNode.createMoveToNode(this.rootSlot);
    10. }
    11. build() {
    12. Scroll() {
    13. Column({ space: 15 }) {
    14. Column() {
    15. ContentSlot(this.rootSlot)
    16. }
    17. }
    18. .width('100%')
    19. }.scrollBarColor(Color.Transparent)
    20. }
    21. }
  2. 新建MoveTo.h文件,在其中创建Stack节点,通过OH_ArkUI_NodeUtils_MoveTo接口移动Stack节点。

    收起
    自动换行
    深色代码主题
    复制
    1. // MoveToExample.h
    2. #ifndef MYAPPLICATION_MOVETO_H
    3. #define MYAPPLICATION_MOVETO_H
    4. #include "ArkUINode.h"
    5. #include <hilog/log.h>
    6. namespace NativeModule {
    7. std::shared_ptr<ArkUIBaseNode> CreateMoveToExample()
    8. {
    9. auto nodeAPI = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
    10. // 创建传入事件节点结构体
    11. struct A {
    12. ArkUI_NodeHandle node;
    13. ArkUI_NodeHandle targetParent;
    14. };
    15. A* a = new A;
    16. // 创建根节点Scroll
    17. ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_SCROLL);
    18. ArkUI_NumberValue length_value[] = {{.f32 = 480}};
    19. ArkUI_AttributeItem length_item = {length_value, sizeof(length_value) / sizeof(ArkUI_NumberValue)};
    20. nodeAPI->setAttribute(scroll, NODE_WIDTH, &length_item);
    21. ArkUI_NumberValue length_value1[] = {{.f32 = 650}};
    22. ArkUI_AttributeItem length_item1 = {length_value1, sizeof(length_value1) / sizeof(ArkUI_NumberValue)};
    23. nodeAPI->setAttribute(scroll, NODE_HEIGHT, &length_item1);
    24. ArkUI_AttributeItem scroll_id = {.string = "Scroll_CAPI"};
    25. nodeAPI->setAttribute(scroll, NODE_ID, &scroll_id);
    26. // 创建Column
    27. ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    28. ArkUI_NumberValue value[] = {480};
    29. ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    30. nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    31. ArkUI_AttributeItem column_id = {.string = "Column_CAPI"};
    32. nodeAPI->setAttribute(column, NODE_ID, &column_id);
    33. // 创建Row
    34. ArkUI_NumberValue text_height[] = {50};
    35. ArkUI_AttributeItem text_item1 = {text_height, sizeof(text_height) / sizeof(ArkUI_NumberValue)};
    36. ArkUI_NumberValue margin[] = {10};
    37. ArkUI_AttributeItem item_margin = {margin, sizeof(margin) / sizeof(ArkUI_NumberValue)};
    38. ArkUI_NodeHandle row0 = nodeAPI->createNode(ARKUI_NODE_ROW);
    39. ArkUI_NumberValue width_value[] = {{.f32=330}};
    40. ArkUI_AttributeItem width_item = {width_value, sizeof(width_value) / sizeof(ArkUI_NumberValue)};
    41. nodeAPI->setAttribute(row0, NODE_WIDTH, &width_item);
    42. nodeAPI->setAttribute(row0, NODE_HEIGHT, &text_item1);
    43. nodeAPI->setAttribute(row0, NODE_MARGIN, &item_margin);
    44. ArkUI_NodeHandle row1 = nodeAPI->createNode(ARKUI_NODE_ROW);
    45. nodeAPI->setAttribute(row1, NODE_WIDTH, &width_item);
    46. nodeAPI->setAttribute(row1, NODE_HEIGHT, &text_item1);
    47. nodeAPI->setAttribute(row1, NODE_MARGIN, &item_margin);
    48. a->targetParent = row1;
    49. ArkUI_NodeHandle row2 = nodeAPI->createNode(ARKUI_NODE_ROW);
    50. nodeAPI->setAttribute(row2, NODE_WIDTH, &width_item);
    51. nodeAPI->setAttribute(row2, NODE_HEIGHT, &text_item1);
    52. nodeAPI->setAttribute(row2, NODE_MARGIN, &item_margin);
    53. // 创建Stack
    54. ArkUI_NodeHandle stack0 = nodeAPI->createNode(ARKUI_NODE_STACK);
    55. ArkUI_NumberValue stack_value[] = {{.f32=50}};
    56. ArkUI_AttributeItem stack_item1 = {stack_value, sizeof(stack_value) / sizeof(ArkUI_NumberValue)};
    57. nodeAPI->setAttribute(stack0, NODE_WIDTH, &stack_item1);
    58. nodeAPI->setAttribute(stack0, NODE_HEIGHT, &stack_item1);
    59. ArkUI_NumberValue stack_bc[] = {{.u32 = 0xFFFFB6C1}};
    60. ArkUI_AttributeItem stack_item2 = {stack_bc, 1};
    61. nodeAPI->setAttribute(stack0, NODE_BACKGROUND_COLOR, &stack_item2);
    62. a->node = stack0;
    63. ArkUI_NodeHandle stack1 = nodeAPI->createNode(ARKUI_NODE_STACK);
    64. nodeAPI->setAttribute(stack1, NODE_WIDTH, &stack_item1);
    65. nodeAPI->setAttribute(stack1, NODE_HEIGHT, &stack_item1);
    66. ArkUI_NumberValue stack_bc1[] = {{.u32 = 0xFF6495ED}};
    67. ArkUI_AttributeItem stack_item3 = {stack_bc1, 1};
    68. nodeAPI->setAttribute(stack1, NODE_BACKGROUND_COLOR, &stack_item3);
    69. ArkUI_NodeHandle stack2 = nodeAPI->createNode(ARKUI_NODE_STACK);
    70. nodeAPI->setAttribute(stack2, NODE_WIDTH, &stack_item1);
    71. nodeAPI->setAttribute(stack2, NODE_HEIGHT, &stack_item1);
    72. ArkUI_NumberValue stack_bc2[] = {{.u32 = 0xFF90EE90}};
    73. ArkUI_AttributeItem stack_item4 = {stack_bc2, 1};
    74. nodeAPI->setAttribute(stack2, NODE_BACKGROUND_COLOR, &stack_item4);
    75. ArkUI_NodeHandle stack3 = nodeAPI->createNode(ARKUI_NODE_STACK);
    76. nodeAPI->setAttribute(stack3, NODE_WIDTH, &stack_item1);
    77. nodeAPI->setAttribute(stack3, NODE_HEIGHT, &stack_item1);
    78. nodeAPI->setAttribute(stack3, NODE_BACKGROUND_COLOR, &stack_item2);
    79. ArkUI_NodeHandle stack4 = nodeAPI->createNode(ARKUI_NODE_STACK);
    80. nodeAPI->setAttribute(stack4, NODE_WIDTH, &stack_item1);
    81. nodeAPI->setAttribute(stack4, NODE_HEIGHT, &stack_item1);
    82. nodeAPI->setAttribute(stack4, NODE_BACKGROUND_COLOR, &stack_item3);
    83. ArkUI_NodeHandle stack5 = nodeAPI->createNode(ARKUI_NODE_STACK);
    84. nodeAPI->setAttribute(stack5, NODE_WIDTH, &stack_item1);
    85. nodeAPI->setAttribute(stack5, NODE_HEIGHT, &stack_item1);
    86. nodeAPI->setAttribute(stack5, NODE_BACKGROUND_COLOR, &stack_item4);
    87. // 创建Button
    88. ArkUI_NodeHandle bt0 = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    89. ArkUI_NumberValue btn_width[] = {150};
    90. ArkUI_AttributeItem btn_item0 = {btn_width, sizeof(btn_width) / sizeof(ArkUI_NumberValue)};
    91. nodeAPI->setAttribute(bt0, NODE_WIDTH, &btn_item0);
    92. nodeAPI->setAttribute(bt0, NODE_HEIGHT, &text_item1);
    93. nodeAPI->setAttribute(bt0, NODE_MARGIN, &item_margin);
    94. ArkUI_AttributeItem bt0_item = {.string = "MoveTo"};
    95. nodeAPI->setAttribute(bt0, NODE_BUTTON_LABEL, &bt0_item);
    96. nodeAPI->registerNodeEvent(bt0, NODE_ON_CLICK, 0, a);
    97. // 注册事件
    98. auto onClick = [](ArkUI_NodeEvent *event) {
    99. auto nodeAPI = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
    100. if (OH_ArkUI_NodeEvent_GetTargetId(event) == 0) { // MoveTo
    101. ArkUI_NodeHandle eventNode = OH_ArkUI_NodeEvent_GetNodeHandle(event);
    102. A* a = (A*)OH_ArkUI_NodeEvent_GetUserData(event);
    103. if (a != nullptr) {
    104. OH_ArkUI_NodeUtils_MoveTo(a->node, a->targetParent, 2);
    105. nodeAPI->unregisterNodeEvent(eventNode, NODE_ON_CLICK);
    106. delete a;
    107. }
    108. }
    109. };
    110. nodeAPI->registerNodeEventReceiver(onClick);
    111. // 节点添加
    112. nodeAPI->addChild(scroll, column);
    113. nodeAPI->addChild(column, row0);
    114. nodeAPI->addChild(column, row1);
    115. nodeAPI->addChild(column, row2);
    116. nodeAPI->addChild(row0, stack0);
    117. nodeAPI->addChild(row0, stack1);
    118. nodeAPI->addChild(row0, stack2);
    119. nodeAPI->addChild(row1, stack3);
    120. nodeAPI->addChild(row1, stack4);
    121. nodeAPI->addChild(row1, stack5);
    122. nodeAPI->addChild(row2, bt0);
    123. return std::make_shared<ArkUINode>(scroll);
    124. }
    125. } // namespace NativeModule
    126. #endif // MYAPPLICATION_MOVETO_H
  3. 在NativeEntry.cpp中,挂载Native节点。

    收起
    自动换行
    深色代码主题
    复制
    1. // NativeEntry.cpp
    2. #include <arkui/native_node_napi.h>
    3. #include <hilog/log.h>
    4. #include <js_native_api.h>
    5. #include "NativeEntry.h"
    6. #include "MoveToExample.h"
    7. #include "GetNodeByIdExample.h"
    8. namespace NativeModule {
    9. // ...
    10. static napi_value CreateNativeRoot(napi_env env, napi_callback_info info, const char *who, MakeNodeFn makeNodeFn)
    11. {
    12. size_t argc = 1;
    13. napi_value args[1] = {nullptr};
    14. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    15. // 获取NodeContent
    16. ArkUI_NodeContentHandle contentHandle;
    17. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    18. if (contentHandle == nullptr) {
    19. OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, K_LOG_DOMAIN,
    20. "%{public}s nodeContentHandle is null", who);
    21. return nullptr;
    22. }
    23. NativeEntry::GetInstance()->SetContentHandle(contentHandle);
    24. // 创建节点
    25. auto node = makeNodeFn();
    26. // 保持Native侧对象到管理类中,维护生命周期。
    27. NativeEntry::GetInstance()->SetRootNode(node);
    28. return nullptr;
    29. }
    30. napi_value DestroyNativeRoot(napi_env env, napi_callback_info info)
    31. {
    32. // 从管理类中释放Native侧对象。
    33. NativeEntry::GetInstance()->DisposeRootNode();
    34. return nullptr;
    35. }
    36. // ...
    37. } // namespace NativeModule
  4. 运行程序,点击按钮,Stack节点会移动到目标位置。

在当前即时帧触发节点属性更新

从API version 21开始,使用OH_ArkUI_NativeModule_InvalidateAttributes接口,在当前帧即时触发节点属性更新,避免组件切换过程中出现闪烁。

  1. ArkTS侧接入Native组件。

    收起
    自动换行
    深色代码主题
    复制
    1. import testNapi from 'libentry.so';
    2. import { NodeContent } from '@kit.ArkUI';
    3. @Component
    4. struct ImageContent {
    5. private nodeContent: NodeContent = new NodeContent();
    6. aboutToAppear() {
    7. // 通过C-API创建节点,并添加到管理器nodeContent上
    8. testNapi.createNativeNode(this.nodeContent);
    9. }
    10. build() {
    11. Column() {
    12. // 显示nodeContent管理器里存放的Native侧的组件
    13. ContentSlot(this.nodeContent)
    14. }
    15. }
    16. }
    17. @Entry
    18. @Component
    19. struct Index {
    20. @State message: string = 'Hello World';
    21. @State showParent: boolean = true;
    22. build() {
    23. Row() {
    24. Column() {
    25. // $r('app.string.Switch')需要替换为开发者所需的资源文件。
    26. Button($r('app.string.Switch')).onClick(()=>{
    27. this.showParent = !this.showParent;
    28. }).margin(20)
    29. if(this.showParent) {
    30. ImageContent()
    31. } else {
    32. ImageContent()
    33. }
    34. }
    35. .width('100%')
    36. }
    37. .height('100%')
    38. }
    39. }
  2. 新建Attribute_util.h用于设置组件属性。

    收起
    自动换行
    深色代码主题
    复制
    1. #ifndef MYAPPLICATION_ATTRIBUTE_UTIL_H
    2. #define MYAPPLICATION_ATTRIBUTE_UTIL_H
    3. #include <arkui/native_node.h>
    4. #include <cstdint>
    5. #include <string>
    6. class AttributeUtil {
    7. public:
    8. ArkUI_NativeNodeAPI_1 *api_;
    9. ArkUI_NodeHandle node_;
    10. AttributeUtil(ArkUI_NodeHandle node, ArkUI_NativeNodeAPI_1 *api)
    11. {
    12. this->node_ = node;
    13. api_ = api;
    14. }
    15. int32_t Width(float width)
    16. {
    17. ArkUI_NumberValue NODE_WIDTH_value[] = {width};
    18. ArkUI_AttributeItem NODE_WIDTH_Item = {NODE_WIDTH_value, 1};
    19. return api_->setAttribute(node_, NODE_WIDTH, &NODE_WIDTH_Item);
    20. }
    21. int32_t Height(float height)
    22. {
    23. ArkUI_NumberValue NODE_HEIGHT_value[] = {height};
    24. ArkUI_AttributeItem NODE_HEIGHT_Item = {NODE_HEIGHT_value, 1};
    25. return api_->setAttribute(node_, NODE_HEIGHT, &NODE_HEIGHT_Item);
    26. }
    27. int32_t ImageSrc(std::string src)
    28. {
    29. ArkUI_AttributeItem NODE_IMAGE_SRC_VALUE = {.string = src.c_str()};
    30. return api_->setAttribute(node_, NODE_IMAGE_SRC, &NODE_IMAGE_SRC_VALUE);
    31. }
    32. int32_t ImageSyncLoad()
    33. {
    34. ArkUI_NumberValue NODE_IMAGE_SYNC_LOAD_value[] = {{.i32 = 1}};
    35. ArkUI_AttributeItem NODE_IMAGE_SYNC_LOAD_item = {NODE_IMAGE_SYNC_LOAD_value, 1};
    36. return api_->setAttribute(node_, NODE_IMAGE_SYNC_LOAD, &NODE_IMAGE_SYNC_LOAD_item);
    37. }
    38. };
    39. #endif // MYAPPLICATION_ATTRIBUTE_UTIL_H
  3. 在napi_init.cpp中,挂载Native节点。

    收起
    自动换行
    深色代码主题
    复制
    1. #include "Attribute_util.h"
    2. #include "napi/native_api.h"
    3. #include <arkui/native_interface.h>
    4. #include <arkui/native_node.h>
    5. #include <arkui/native_node_napi.h>
    6. #include <hilog/log.h>
    7. #include <js_native_api.h>
    8. #include <js_native_api_types.h>
    9. // ...
    10. const unsigned int NUMBER_2 = 2;
    11. const unsigned int NUMBER_WIDTH = 100;
    12. const unsigned int NUMBER_HEIGHT = 100;
    13. static napi_value Add(napi_env env, napi_callback_info info)
    14. {
    15. size_t argc = NUMBER_2;
    16. napi_value args[NUMBER_2] = {nullptr};
    17. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    18. napi_valuetype valuetype0;
    19. napi_typeof(env, args[0], &valuetype0);
    20. napi_valuetype valuetype1;
    21. napi_typeof(env, args[1], &valuetype1);
    22. double value0;
    23. napi_get_value_double(env, args[0], &value0);
    24. double value1;
    25. napi_get_value_double(env, args[1], &value1);
    26. napi_value sum;
    27. napi_create_double(env, value0 + value1, &sum);
    28. return sum;
    29. }
    30. static ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
    31. static napi_value NAPI_Global_createNativeNode(napi_env env, napi_callback_info info)
    32. {
    33. size_t argc = 1;
    34. napi_value args[1] = {nullptr};
    35. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    36. ArkUI_NodeContentHandle contentHandle;
    37. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    38. OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
    39. // 创建Image组件
    40. auto imageNode = nodeAPI->createNode(ARKUI_NODE_IMAGE);
    41. AttributeUtil imageNodeAttr(imageNode, nodeAPI);
    42. // 设置image组件属性
    43. imageNodeAttr.ImageSrc("resources/base/media/startIcon.png");
    44. imageNodeAttr.ImageSyncLoad();
    45. imageNodeAttr.Width(NUMBER_WIDTH);
    46. imageNodeAttr.Height(NUMBER_HEIGHT);
    47. // 在当前即时帧触发节点属性更新
    48. OH_ArkUI_NativeModule_InvalidateAttributes(imageNode);
    49. // 挂载image组件到组件树
    50. OH_ArkUI_NodeContent_AddNode(contentHandle, imageNode);
    51. return nullptr;
    52. }
    53. EXTERN_C_START
    54. static napi_value Init(napi_env env, napi_value exports)
    55. {
    56. napi_property_descriptor desc[] = {
    57. {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
    58. {"createNativeNode", nullptr, NAPI_Global_createNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr},
    59. // ...
    60. };
    61. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    62. return exports;
    63. }
    64. EXTERN_C_END
    65. static napi_module demoModule = {
    66. .nm_version = 1,
    67. .nm_flags = 0,
    68. .nm_filename = nullptr,
    69. .nm_register_func = Init,
    70. .nm_modname = "entry",
    71. .nm_priv = ((void*)0),
    72. .reserved = { 0 },
    73. };
    74. extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
    75. {
    76. napi_module_register(&demoModule);
    77. }
  4. 运行程序,点击按钮,切换图片正常展示。

用不同的展开模式获取对应下标的子节点

NDK支持通过不同的展开方式获取目标节点下的有效节点信息。例如,在LazyForEach场景下,可以处理存在多个子节点的情况。

从API version 20开始,使用OH_ArkUI_NodeUtils_GetFirstChildIndexWithoutExpand接口,可以获取目标节点的第一个存在于组件树的节点。使用OH_ArkUI_NodeUtils_GetLastChildIndexWithoutExpand接口,可以获取目标节点的最后一个存在于组件树的节点。OH_ArkUI_NodeUtils_GetChildWithExpandMode接口,可以通过不同的节点展开模式获取对应下标的子节点。

说明

节点展开方式请参考ArkUI_ExpandMode,此处推荐使用ARKUI_LAZY_EXPAND懒展开方式,智能识别对应场景。

  1. 通过ArkTS构造LazyForEach及ArkTS的下树节点展开场景。

    收起
    自动换行
    深色代码主题
    复制
    1. import { NodeController, FrameNode, UIContext, BuilderNode, ExpandMode, LengthUnit } from '@kit.ArkUI';
    2. const TEST_TAG: string = "FrameNode ";
    3. // BasicDataSource实现了IDataSource接口,用于管理listener监听,以及通知LazyForEach数据更新
    4. class BasicDataSource implements IDataSource {
    5. private listeners: DataChangeListener[] = [];
    6. private originDataArray: string[] = [];
    7. public totalCount(): number {
    8. return 0;
    9. }
    10. public getData(index: number): string {
    11. return this.originDataArray[index];
    12. }
    13. // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
    14. registerDataChangeListener(listener: DataChangeListener): void {
    15. if (this.listeners.indexOf(listener) < 0) {
    16. console.info('add listener');
    17. this.listeners.push(listener);
    18. }
    19. }
    20. // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
    21. unregisterDataChangeListener(listener: DataChangeListener): void {
    22. const pos = this.listeners.indexOf(listener);
    23. if (pos >= 0) {
    24. console.info('remove listener');
    25. this.listeners.splice(pos, 1);
    26. }
    27. }
    28. // 通知LazyForEach组件需要重载所有子组件
    29. notifyDataReload(): void {
    30. this.listeners.forEach(listener => {
    31. listener.onDataReloaded();
    32. })
    33. }
    34. // 通知LazyForEach组件需要在index对应索引处添加子组件
    35. notifyDataAdd(index: number): void {
    36. this.listeners.forEach(listener => {
    37. listener.onDataAdd(index);
    38. // 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);
    39. })
    40. }
    41. // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
    42. notifyDataChange(index: number): void {
    43. this.listeners.forEach(listener => {
    44. listener.onDataChange(index);
    45. // 写法2:listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);
    46. })
    47. }
    48. // 通知LazyForEach组件需要在index对应索引处删除该子组件
    49. notifyDataDelete(index: number): void {
    50. this.listeners.forEach(listener => {
    51. listener.onDataDelete(index);
    52. // 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);
    53. })
    54. }
    55. // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
    56. notifyDataMove(from: number, to: number): void {
    57. this.listeners.forEach(listener => {
    58. listener.onDataMove(from, to);
    59. // 写法2:listener.onDatasetChange(
    60. // [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);
    61. })
    62. }
    63. notifyDatasetChange(operations: DataOperation[]): void {
    64. this.listeners.forEach(listener => {
    65. listener.onDatasetChange(operations);
    66. })
    67. }
    68. }
    69. class MyDataSource extends BasicDataSource {
    70. private dataArray: string[] = []
    71. public totalCount(): number {
    72. return this.dataArray.length;
    73. }
    74. public getData(index: number): string {
    75. return this.dataArray[index];
    76. }
    77. public addData(index: number, data: string): void {
    78. this.dataArray.splice(index, 0, data);
    79. this.notifyDataAdd(index);
    80. }
    81. public pushData(data: string): void {
    82. this.dataArray.push(data);
    83. this.notifyDataAdd(this.dataArray.length - 1);
    84. }
    85. }
    86. class Params {
    87. data: MyDataSource | null = null;
    88. scroller: Scroller | null = null;
    89. constructor(data: MyDataSource, scroller: Scroller) {
    90. this.data = data;
    91. this.scroller = scroller;
    92. }
    93. }
    94. @Builder
    95. function buildData(params: Params) {
    96. List({ scroller: params.scroller }) {
    97. LazyForEach(params.data, (item: string) => {
    98. ListItem() {
    99. Column() {
    100. Text(item)
    101. .fontSize(20)
    102. .onAppear(() => {
    103. console.info(TEST_TAG + " node appear: " + item)
    104. })
    105. .backgroundColor(Color.Pink)
    106. .margin({
    107. top: 30,
    108. bottom: 30,
    109. left: 10,
    110. right: 10
    111. })
    112. }
    113. }
    114. .id(item)
    115. }, (item: string) => item)
    116. }
    117. .cachedCount(5)
    118. .listDirection(Axis.Horizontal)
    119. }
    120. class MyNodeController extends NodeController {
    121. private rootNode: FrameNode | null = null;
    122. private uiContext: UIContext | null = null;
    123. private data: MyDataSource = new MyDataSource();
    124. private scroller: Scroller = new Scroller();
    125. makeNode(uiContext: UIContext): FrameNode | null {
    126. this.uiContext = uiContext;
    127. for (let i = 0; i <= 20; i++) {
    128. this.data.pushData(`N${i}`);
    129. }
    130. const params: Params = new Params(this.data, this.scroller);
    131. const dataNode: BuilderNode<[Params]> = new BuilderNode(uiContext);
    132. dataNode.build(wrapBuilder<[Params]>(buildData), params);
    133. this.rootNode = dataNode.getFrameNode();
    134. const scrollToIndexOptions: ScrollToIndexOptions = {
    135. extraOffset: {
    136. value: 20, unit: LengthUnit.VP
    137. }
    138. };
    139. this.scroller.scrollToIndex(6, true, ScrollAlign.START, scrollToIndexOptions);
    140. return this.rootNode;
    141. }
    142. // 获取不展开场景下第一个活跃节点的下标
    143. getFirstChildIndexWithoutExpand() {
    144. console.info(`${TEST_TAG} getFirstChildIndexWithoutExpand: ${this.rootNode!.getFirstChildIndexWithoutExpand()}`);
    145. }
    146. // 获取不展开场景下最后一个活跃节点的下标
    147. getLastChildIndexWithoutExpand() {
    148. console.info(`${TEST_TAG} getLastChildIndexWithoutExpand: ${this.rootNode!.getLastChildIndexWithoutExpand()}`);
    149. }
    150. // 用不展开的方式获取节点
    151. getChildWithNotExpand() {
    152. const childNode = this.rootNode!.getChild(3, ExpandMode.NOT_EXPAND);
    153. console.info(TEST_TAG + " getChild(3, ExpandMode.NOT_EXPAND): " + childNode?.getId());
    154. if (childNode?.getId() === "N9") {
    155. console.info(TEST_TAG + " getChild(3, ExpandMode.NOT_EXPAND) result: success.");
    156. } else {
    157. console.info(TEST_TAG + " getChild(3, ExpandMode.NOT_EXPAND) result: fail.");
    158. }
    159. }
    160. // 以展开的方式获取节点
    161. getChildWithExpand() {
    162. const childNode = this.rootNode!.getChild(3, ExpandMode.EXPAND);
    163. console.info(TEST_TAG + " getChild(3, ExpandMode.EXPAND): " + childNode?.getId());
    164. if (childNode?.getId() === "N3") {
    165. console.info(TEST_TAG + " getChild(3, ExpandMode.EXPAND) result: success.");
    166. } else {
    167. console.info(TEST_TAG + " getChild(3, ExpandMode.EXPAND) result: fail.");
    168. }
    169. }
    170. getChildWithLazyExpand() {
    171. const childNode = this.rootNode!.getChild(3, ExpandMode.LAZY_EXPAND);
    172. console.info(TEST_TAG + " getChild(3, ExpandMode.LAZY_EXPAND): " + childNode?.getId());
    173. if (childNode?.getId() === "N3") {
    174. console.info(TEST_TAG + " getChild(3, ExpandMode.LAZY_EXPAND) result: success.");
    175. } else {
    176. console.info(TEST_TAG + " getChild(3, ExpandMode.LAZY_EXPAND) result: fail.");
    177. }
    178. }
    179. }
    180. @Entry
    181. @Component
    182. struct Index {
    183. private myNodeController: MyNodeController = new MyNodeController();
    184. private scroller: Scroller = new Scroller();
    185. build() {
    186. Scroll(this.scroller) {
    187. Column({ space: 8 }) {
    188. Column() {
    189. Text("This is a NodeContainer.")
    190. .textAlign(TextAlign.Center)
    191. .borderRadius(10)
    192. .backgroundColor(0xFFFFFF)
    193. .width('100%')
    194. .fontSize(16)
    195. NodeContainer(this.myNodeController)
    196. .borderWidth(1)
    197. .width(300)
    198. .height(100)
    199. }
    200. Button("getFirstChildIndexWithoutExpand")
    201. .width(300)
    202. .onClick(() => {
    203. this.myNodeController.getFirstChildIndexWithoutExpand();
    204. })
    205. Button("getLastChildIndexWithoutExpand")
    206. .width(300)
    207. .onClick(() => {
    208. this.myNodeController.getLastChildIndexWithoutExpand();
    209. })
    210. Button("getChildWithNotExpand")
    211. .width(300)
    212. .onClick(() => {
    213. this.myNodeController.getChildWithNotExpand();
    214. })
    215. Button("getChildWithExpand")
    216. .width(300)
    217. .onClick(() => {
    218. this.myNodeController.getChildWithExpand();
    219. })
    220. Button("getChildWithLazyExpand")
    221. .width(300)
    222. .onClick(() => {
    223. this.myNodeController.getChildWithLazyExpand();
    224. })
    225. }
    226. .width("100%")
    227. }
    228. .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
    229. }
    230. }
  2. NDK侧通过OH_ArkUI_NodeUtils_GetAttachedNodeHandleById接口获取ArkTS组件,并通过懒展开模式获取对应的子组件信息。

    收起
    自动换行
    深色代码主题
    复制
    1. ArkUI_NodeHandle childNode = nullptr;
    2. OH_ArkUI_NodeUtils_GetAttachedNodeHandleById("N3", &childNode);
    3. uint32_t index = 0;
    4. OH_ArkUI_NodeUtils_GetFirstChildIndexWithoutExpand(childNode, &index);
    5. uint32_t index1 = 0;
    6. OH_ArkUI_NodeUtils_GetLastChildIndexWithoutExpand(childNode, &index1);
    7. ArkUI_NodeHandle child = nullptr;
    8. auto result = OH_ArkUI_NodeUtils_GetChildWithExpandMode(childNode, 3, &child, 0);
    9. OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "Manager",
    10. "firstChildIndex - lastChildIndex == %{public}d -- %{public}d, -- getResult = %{public}d",
    11. index, index1, result);
  3. 查看日志打印的对应错误码返回是否正确,以此判断是否成功获取到对应子节点。

节点是否处于渲染状态

从API version 23开始,使用OH_ArkUI_NativeModule_IsInRenderState接口,可以查询节点是否在渲染树上。

  1. ArkTS侧接入Native组件。

    收起
    自动换行
    深色代码主题
    复制
    1. //Index.ets
    2. import testNapi from 'libentry.so';
    3. import { NodeContent } from '@kit.ArkUI';
    4. @Component
    5. struct TestContent {
    6. private nodeContent: NodeContent = new NodeContent();
    7. aboutToAppear() {
    8. // 通过C-API创建节点,并添加到管理器nodeContent上
    9. testNapi.createNativeNode(this.nodeContent);
    10. }
    11. build() {
    12. Column() {
    13. // 显示nodeContent管理器里存放的Native侧的组件
    14. ContentSlot(this.nodeContent)
    15. }
    16. }
    17. }
    18. @Entry
    19. @Component
    20. struct Index {
    21. @State message: string = 'Hello World';
    22. @State showParent: boolean = true;
    23. build() {
    24. Row() {
    25. Column() {
    26. TestContent()
    27. }
    28. .width('100%')
    29. }
    30. .height('100%')
    31. }
    32. }
  2. 新建Attribute_util.h用于设置组件属性。

    收起
    自动换行
    深色代码主题
    复制
    1. #ifndef MYAPPLICATION_ATTRIBUTE_UTIL_H
    2. #define MYAPPLICATION_ATTRIBUTE_UTIL_H
    3. #include <arkui/native_node.h>
    4. #include <cstdint>
    5. #include <string>
    6. class AttributeUtil {
    7. public:
    8. ArkUI_NativeNodeAPI_1 *api_;
    9. ArkUI_NodeHandle node_;
    10. AttributeUtil(ArkUI_NodeHandle node, ArkUI_NativeNodeAPI_1 *api) {
    11. this->node_ = node;
    12. api_ = api;
    13. }
    14. int32_t width(float width) {
    15. ArkUI_NumberValue NODE_WIDTH_value[] = {width};
    16. ArkUI_AttributeItem NODE_WIDTH_Item = {NODE_WIDTH_value, 1};
    17. return api_->setAttribute(node_, NODE_WIDTH, &NODE_WIDTH_Item);
    18. }
    19. int32_t height(float height) {
    20. ArkUI_NumberValue NODE_HEIGHT_value[] = {height};
    21. ArkUI_AttributeItem NODE_HEIGHT_Item = {NODE_HEIGHT_value, 1};
    22. return api_->setAttribute(node_, NODE_HEIGHT, &NODE_HEIGHT_Item);
    23. }
    24. int32_t buttonLabel(std::string text) {
    25. ArkUI_AttributeItem NODE_TRANSLATE_ITEM_LABEL = {.string = text.c_str()};
    26. return api_->setAttribute(node_, NODE_BUTTON_LABEL, &NODE_TRANSLATE_ITEM_LABEL);
    27. }
    28. int32_t text(std::string str) {
    29. ArkUI_AttributeItem TEXT_ITEM = {.string = str.c_str()};
    30. return api_->setAttribute(node_, NODE_TEXT_CONTENT, &TEXT_ITEM);
    31. }
    32. int32_t visibility(int isShow) {
    33. ArkUI_NumberValue NODE_VISIBILITY_ITEM_VALUE = {.i32 = isShow};
    34. ArkUI_AttributeItem NODE_VISIBILITY_ITEM = {&NODE_VISIBILITY_ITEM_VALUE, 1};
    35. return api_->setAttribute(node_, NODE_VISIBILITY, &NODE_VISIBILITY_ITEM);
    36. }
    37. int32_t margin(float value) {
    38. ArkUI_NumberValue NODE_MARGIN_ITEM_VALUE = {.f32 = value};
    39. ArkUI_AttributeItem NODE_MARGIN_ITEM = {&NODE_MARGIN_ITEM_VALUE, 1};
    40. return api_->setAttribute(node_, NODE_MARGIN, &NODE_MARGIN_ITEM);
    41. }
    42. };
    43. #endif // MYAPPLICATION_ATTRIBUTE_UTIL_H
  3. 在napi_init.cpp中,挂载Native节点。

    收起
    自动换行
    深色代码主题
    复制
    1. #include "napi/native_api.h"
    2. #include "Attribute_util.h"
    3. #include <arkui/native_interface.h>
    4. #include <arkui/native_node.h>
    5. #include <arkui/native_node_napi.h>
    6. #include <hilog/log.h>
    7. static ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
    8. static ArkUI_NodeHandle textNode = nullptr;
    9. static bool showText = false;
    10. namespace Event {
    11. void onClickFunc(ArkUI_NodeEvent *event) {
    12. AttributeUtil textAttr(textNode, nodeAPI);
    13. if (showText) {
    14. textAttr.visibility(0);
    15. } else {
    16. textAttr.visibility(1);
    17. }
    18. showText = !showText;
    19. bool isOnRenderTree = false;
    20. OH_ArkUI_NativeModule_IsInRenderState(textNode, &isOnRenderTree);
    21. OH_LOG_Print(LOG_APP, LOG_INFO, 1, "event","on render tree state is %{public}d", isOnRenderTree);
    22. }
    23. } // namespace Event
    24. static napi_value NAPI_Global_createNativeNode(napi_env env, napi_callback_info info) {
    25. size_t argc = 1;
    26. napi_value args[1] = {nullptr};
    27. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    28. ArkUI_NodeContentHandle contentHandle;
    29. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    30. OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
    31. auto columnTest = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    32. AttributeUtil columnAttr(columnTest, nodeAPI);
    33. columnAttr.width(300);
    34. columnAttr.height(300);
    35. auto buttonNode = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    36. nodeAPI->addChild(columnTest, buttonNode);
    37. AttributeUtil buttonAttr(buttonNode, nodeAPI);
    38. buttonAttr.width(200);
    39. buttonAttr.height(30);
    40. buttonAttr.margin(20);
    41. buttonAttr.buttonLabel("change text visibility");
    42. nodeAPI->registerNodeEvent(buttonNode, NODE_ON_CLICK, 1, nullptr);
    43. nodeAPI->registerNodeEventReceiver(Event::onClickFunc);
    44. textNode = nodeAPI->createNode(ARKUI_NODE_TEXT);
    45. nodeAPI->addChild(columnTest, textNode);
    46. AttributeUtil textAttr(textNode, nodeAPI);
    47. textAttr.text("hello world");
    48. OH_ArkUI_NodeContent_AddNode(contentHandle, columnTest);
    49. return nullptr;
    50. }
    51. EXTERN_C_START
    52. static napi_value Init(napi_env env, napi_value exports) {
    53. napi_property_descriptor desc[] = {
    54. {"createNativeNode", nullptr, NAPI_Global_createNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}};
    55. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    56. return exports;
    57. }
    58. EXTERN_C_END
    59. static napi_module demoModule = {
    60. .nm_version = 1,
    61. .nm_flags = 0,
    62. .nm_filename = nullptr,
    63. .nm_register_func = Init,
    64. .nm_modname = "entry",
    65. .nm_priv = ((void *)0),
    66. .reserved = {0},
    67. };
    68. extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
  4. 运行程序,点击change text visibility后打印text是否在渲染树上。

在 指南 中进行搜索
请输入您想要搜索的关键词