文档管理中心

构建渲染节点

从API version 20开始,ArkUI开发框架针对NDK接口,提供了直接构建渲染节点的能力,包括节点树操作、属性设置及含动画的自定义绘制。开发者通过调用渲染节点相关能力,可以绕过registerNodeCustomEvent的测量布局过程,直接对节点进行绘制并调整其大小和位置。

节点挂载与基础属性设置

以下示例创建了一个渲染节点,并进行了基础的节点挂载和属性设置操作。

  1. 按照接入ArkTS页面创建前置工程。

  2. 创建渲染节点能力对象。

    收起
    自动换行
    深色代码主题
    复制
    1. // NativeEntry.cpp
    2. // 自定义容器组件示例。
    3. #include <arkui/native_animate.h>
    4. #include <arkui/native_render.h>
    5. #include <arkui/native_type.h>
    6. #include <arkui/native_node_napi.h>
    7. #include <bits/alltypes.h>
    8. #include <string>
    9. #include <arkui/native_interface.h>
    10. #include <arkui/native_node.h>
    11. #include <native_drawing/drawing_canvas.h>
    12. #include <native_drawing/drawing_color.h>
    13. #include <native_drawing/drawing_path.h>
    14. #include <native_drawing/drawing_pen.h>
    15. ArkUI_NodeHandle testRenderNode(ArkUI_NativeNodeAPI_1 *nodeAPI) {
    16. // 创建NDK原有容器逻辑。
    17. ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_SCROLL);
    18. ArkUI_NumberValue valueWidth[] = {400};
    19. ArkUI_AttributeItem itemWidth = {valueWidth, sizeof(valueWidth) / sizeof(ArkUI_NumberValue)};
    20. nodeAPI->setAttribute(scroll, NODE_WIDTH, &itemWidth);
    21. ArkUI_NumberValue valueHeight[] = {600};
    22. ArkUI_AttributeItem itemHeight = {valueHeight, sizeof(valueHeight) / sizeof(ArkUI_NumberValue)};
    23. nodeAPI->setAttribute(scroll, NODE_HEIGHT, &itemHeight);
    24. ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    25. nodeAPI->setAttribute(column, NODE_WIDTH, &itemWidth);
    26. nodeAPI->setAttribute(column, NODE_HEIGHT, &itemHeight);
    27. ArkUI_NodeHandle text = nodeAPI->createNode(ARKUI_NODE_TEXT);
    28. ArkUI_AttributeItem content = {.string = "黄色背景是C-API页面"};
    29. nodeAPI->setAttribute(text, NODE_TEXT_CONTENT, &content);
    30. nodeAPI->addChild(column, text);
    31. // 创建RenderNode容器 -- NDK侧的Custom组件。
    32. ArkUI_NodeHandle Custom = nodeAPI->createNode(ARKUI_NODE_CUSTOM);
    33. valueWidth[0].f32 = 400;
    34. nodeAPI->setAttribute(Custom, NODE_WIDTH, &itemWidth);
    35. nodeAPI->setAttribute(Custom, NODE_HEIGHT, &itemHeight);
    36. nodeAPI->addChild(column, Custom);
    37. // 节点操作类接口 创建 - 挂载 - 构建树。
    38. // 创建部分。
    39. auto renderRootNode = OH_ArkUI_RenderNodeUtils_CreateNode();
    40. auto firstChildRenderNode = OH_ArkUI_RenderNodeUtils_CreateNode();
    41. auto secondChildRenderNode = OH_ArkUI_RenderNodeUtils_CreateNode();
    42. auto thirdChildRenderNode = OH_ArkUI_RenderNodeUtils_CreateNode();
    43. auto result = OH_ArkUI_RenderNodeUtils_AddRenderNode(Custom, renderRootNode);
    44. if (result != ARKUI_ERROR_CODE_NO_ERROR) {
    45. // 通过错误码判断根节点是否挂载成功。
    46. return scroll;
    47. }
    48. OH_ArkUI_RenderNodeUtils_AddChild(renderRootNode, firstChildRenderNode);
    49. OH_ArkUI_RenderNodeUtils_AddChild(renderRootNode, secondChildRenderNode);
    50. OH_ArkUI_RenderNodeUtils_AddChild(renderRootNode, thirdChildRenderNode);
    51. // 设置节点尺寸与位置。
    52. OH_ArkUI_RenderNodeUtils_SetSize(renderRootNode, 500, 500);
    53. OH_ArkUI_RenderNodeUtils_SetSize(firstChildRenderNode, 120, 120);
    54. OH_ArkUI_RenderNodeUtils_SetSize(secondChildRenderNode, 120, 120);
    55. OH_ArkUI_RenderNodeUtils_SetSize(thirdChildRenderNode, 120, 120);
    56. OH_ArkUI_RenderNodeUtils_SetPosition(renderRootNode, 300, 100);
    57. OH_ArkUI_RenderNodeUtils_SetPosition(firstChildRenderNode, 0, 0);
    58. OH_ArkUI_RenderNodeUtils_SetPosition(secondChildRenderNode, 140, 140);
    59. OH_ArkUI_RenderNodeUtils_SetPosition(thirdChildRenderNode, 280, 280);
    60. // 设置颜色,方便通过颜色观察到节点的显示范围。
    61. OH_ArkUI_RenderNodeUtils_SetBackgroundColor(renderRootNode, 0xFFFFFFFF);
    62. OH_ArkUI_RenderNodeUtils_SetBackgroundColor(firstChildRenderNode, 0xFFFF0000); // R
    63. OH_ArkUI_RenderNodeUtils_SetBackgroundColor(secondChildRenderNode, 0xFF00FF00); // G
    64. OH_ArkUI_RenderNodeUtils_SetBackgroundColor(thirdChildRenderNode, 0xFF0000FF); // B
    65. // 简单的属性设置示例。
    66. OH_ArkUI_RenderNodeUtils_SetRotation(secondChildRenderNode, 45, 45, 0); // xy轴旋转45度,z轴旋转0度
    67. // 边框属性实例。
    68. auto styleOption = OH_ArkUI_RenderNodeUtils_CreateNodeBorderStyleOption();
    69. OH_ArkUI_RenderNodeUtils_SetNodeBorderStyleOptionEdgeStyle(styleOption, ArkUI_BorderStyle::ARKUI_BORDER_STYLE_SOLID,
    70. ArkUI_EdgeDirection::ARKUI_EDGE_DIRECTION_ALL);
    71. OH_ArkUI_RenderNodeUtils_SetBorderStyle(firstChildRenderNode, styleOption);
    72. // 结构体使用完成后,销毁释放内存。
    73. OH_ArkUI_RenderNodeUtils_DisposeNodeBorderStyleOption(styleOption);
    74. styleOption = nullptr;
    75. auto widthOption = OH_ArkUI_RenderNodeUtils_CreateNodeBorderWidthOption();
    76. OH_ArkUI_RenderNodeUtils_SetNodeBorderWidthOptionEdgeWidth(widthOption, 5,
    77. ArkUI_EdgeDirection::ARKUI_EDGE_DIRECTION_ALL);
    78. OH_ArkUI_RenderNodeUtils_SetBorderWidth(firstChildRenderNode, widthOption);
    79. // 结构体使用完成后,销毁释放内存。
    80. OH_ArkUI_RenderNodeUtils_DisposeNodeBorderWidthOption(widthOption);
    81. widthOption = nullptr;
    82. auto colorOption = OH_ArkUI_RenderNodeUtils_CreateNodeBorderColorOption();
    83. OH_ArkUI_RenderNodeUtils_SetNodeBorderColorOptionEdgeColor(colorOption, 0xFF000000,
    84. ArkUI_EdgeDirection::ARKUI_EDGE_DIRECTION_ALL);
    85. result = OH_ArkUI_RenderNodeUtils_SetBorderColor(firstChildRenderNode, colorOption);
    86. // 结构体使用完成后,销毁释放内存。
    87. OH_ArkUI_RenderNodeUtils_DisposeNodeBorderColorOption(colorOption);
    88. colorOption = nullptr;
    89. nodeAPI->addChild(scroll, column);
    90. return scroll;
    91. }
    92. napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
    93. size_t argc = 1;
    94. napi_value args[1] = {nullptr};
    95. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    96. auto *nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
    97. OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
    98. ArkUI_NodeHandle testNode = nullptr;
    99. if (nodeAPI != nullptr) {
    100. testNode = testRenderNode(nodeAPI);
    101. }
    102. NativeEntry::GetInstance()->SetRootNode(testNode);
    103. return nullptr;
    104. }

自定义绘制及动画

以下示例创建了一个渲染节点,调用自定义绘制能力并附加动画功能。

  1. 按照接入ArkTS页面创建前置工程。

  2. 创建渲染节点能力对象。

    收起
    自动换行
    深色代码主题
    复制
    1. // NativeEntry.cpp
    2. // 自定义容器组件示例。
    3. #include <arkui/native_animate.h>
    4. #include <arkui/native_render.h>
    5. #include <arkui/native_type.h>
    6. #include <arkui/native_node_napi.h>
    7. #include <bits/alltypes.h>
    8. #include <string>
    9. #include <arkui/native_interface.h>
    10. #include <arkui/native_node.h>
    11. #include <native_drawing/drawing_canvas.h>
    12. #include <native_drawing/drawing_color.h>
    13. #include <native_drawing/drawing_path.h>
    14. #include <native_drawing/drawing_pen.h>
    15. ArkUI_NodeHandle testRenderNode2(ArkUI_NativeNodeAPI_1 *nodeAPI, ArkUI_ContextHandle context) {
    16. ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    17. ArkUI_NumberValue valueWidth[] = {400};
    18. ArkUI_AttributeItem itemWidth = {valueWidth, sizeof(valueWidth) / sizeof(ArkUI_NumberValue)};
    19. nodeAPI->setAttribute(scroll, NODE_WIDTH, &itemWidth);
    20. ArkUI_NumberValue valueHeight[] = {600};
    21. ArkUI_AttributeItem itemHeight = {valueHeight, sizeof(valueHeight) / sizeof(ArkUI_NumberValue)};
    22. nodeAPI->setAttribute(scroll, NODE_HEIGHT, &itemHeight);
    23. valueHeight[0].u32 = 0xff00F100;
    24. nodeAPI->setAttribute(scroll, NODE_BACKGROUND_COLOR, &itemHeight);
    25. ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    26. ArkUI_NodeHandle text = nodeAPI->createNode(ARKUI_NODE_TEXT);
    27. ArkUI_AttributeItem content = {.string = "这是C-API页面"};
    28. nodeAPI->setAttribute(text, NODE_TEXT_CONTENT, &content);
    29. ArkUI_NodeHandle Custom = nodeAPI->createNode(ARKUI_NODE_CUSTOM);
    30. auto renderNode = OH_ArkUI_RenderNodeUtils_CreateNode();
    31. OH_ArkUI_RenderNodeUtils_AddRenderNode(Custom, renderNode);
    32. OH_ArkUI_RenderNodeUtils_SetSize(renderNode, 1000, 1000);
    33. // Property的作用是触发set更新,同步更新modifier的Draw方法。
    34. struct AnimatableUserData {
    35. ArkUI_FloatAnimatablePropertyHandle width;
    36. ArkUI_FloatAnimatablePropertyHandle height;
    37. ArkUI_Vector2AnimatablePropertyHandle v2;
    38. ArkUI_ColorAnimatablePropertyHandle color;
    39. };
    40. // 设置基础值。
    41. AnimatableUserData *userData1 = new AnimatableUserData;
    42. auto widthAnimProperty = OH_ArkUI_RenderNodeUtils_CreateFloatAnimatableProperty(1000);
    43. userData1->width = widthAnimProperty;
    44. auto heightAnimProperty = OH_ArkUI_RenderNodeUtils_CreateFloatAnimatableProperty(1000);
    45. userData1->height = heightAnimProperty;
    46. auto vectorAnimP = OH_ArkUI_RenderNodeUtils_CreateVector2AnimatableProperty(1000, 1000);
    47. userData1->v2 = vectorAnimP;
    48. auto colorAnimP = OH_ArkUI_RenderNodeUtils_CreateColorAnimatableProperty(0xFFFF11FF);
    49. userData1->color = colorAnimP;
    50. // 关联组件和多个modifier。
    51. auto animModifier = OH_ArkUI_RenderNodeUtils_CreateContentModifier();
    52. OH_ArkUI_RenderNodeUtils_AttachContentModifier(renderNode, animModifier);
    53. // 关联modifier和property。
    54. OH_ArkUI_RenderNodeUtils_AttachFloatAnimatableProperty(animModifier, widthAnimProperty);
    55. OH_ArkUI_RenderNodeUtils_AttachFloatAnimatableProperty(animModifier, heightAnimProperty);
    56. OH_ArkUI_RenderNodeUtils_AttachVector2AnimatableProperty(animModifier, vectorAnimP);
    57. OH_ArkUI_RenderNodeUtils_AttachColorAnimatableProperty(animModifier, colorAnimP);
    58. // 设置自定义绘制内容。
    59. OH_ArkUI_RenderNodeUtils_SetContentModifierOnDraw(
    60. animModifier, userData1, [](ArkUI_DrawContext *context, void *userData) {
    61. AnimatableUserData *data = (AnimatableUserData *)userData;
    62. float width = 0;
    63. float height = 0;
    64. uint32_t color = 0;
    65. ArkUI_Vector2AnimatablePropertyHandle v2 = data->v2;
    66. // property主要为传值用,这里用x,y来替代width,实际使用时可以通过property来自定义所需参数。
    67. OH_ArkUI_RenderNodeUtils_GetVector2AnimatablePropertyValue(v2, &width, &height);
    68. ArkUI_ColorAnimatablePropertyHandle cp = data->color;
    69. OH_ArkUI_RenderNodeUtils_GetColorAnimatablePropertyValue(cp, &color);
    70. auto *canvas1 = OH_ArkUI_DrawContext_GetCanvas(context);
    71. OH_Drawing_Canvas *canvas = reinterpret_cast<OH_Drawing_Canvas *>(canvas1);
    72. auto path = OH_Drawing_PathCreate();
    73. OH_Drawing_PathMoveTo(path, width / 4, height / 4);
    74. OH_Drawing_PathLineTo(path, width * 3 / 4, height / 4);
    75. OH_Drawing_PathLineTo(path, width * 3 / 4, height * 3 / 4);
    76. OH_Drawing_PathLineTo(path, width / 4, height * 3 / 4);
    77. OH_Drawing_PathLineTo(path, width / 4, height / 4);
    78. OH_Drawing_PathClose(path);
    79. auto pen = OH_Drawing_PenCreate();
    80. OH_Drawing_PenSetWidth(pen, 10);
    81. OH_Drawing_PenSetColor(pen, color);
    82. OH_Drawing_CanvasAttachPen(canvas, pen);
    83. OH_Drawing_CanvasDrawPath(canvas, path);
    84. OH_Drawing_CanvasDetachPen(canvas);
    85. OH_Drawing_PenDestroy(pen);
    86. OH_Drawing_PathDestroy(path);
    87. });
    88. // 用户自定义参数。
    89. ArkUI_ContextCallback *update = new ArkUI_ContextCallback;
    90. update->userData = userData1;
    91. update->callback = [](void *user) {
    92. AnimatableUserData *data = (AnimatableUserData *)user;
    93. OH_ArkUI_RenderNodeUtils_SetFloatAnimatablePropertyValue(data->width, 100);
    94. OH_ArkUI_RenderNodeUtils_SetFloatAnimatablePropertyValue(data->height, 100);
    95. OH_ArkUI_RenderNodeUtils_SetVector2AnimatablePropertyValue(data->v2, 100, 100);
    96. OH_ArkUI_RenderNodeUtils_SetColorAnimatablePropertyValue(data->color, 0xFF0011FF);
    97. };
    98. // 执行对应的动画。
    99. ArkUI_NativeAnimateAPI_1 *animateApi = nullptr;
    100. OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_ANIMATE, ArkUI_NativeAnimateAPI_1, animateApi);
    101. ArkUI_AnimateCompleteCallback *completeCallback = new ArkUI_AnimateCompleteCallback;
    102. completeCallback->userData = userData1;
    103. completeCallback->type = ARKUI_FINISH_CALLBACK_REMOVED;
    104. completeCallback->callback = [](void *userData) {
    105. AnimatableUserData *data = (AnimatableUserData *)userData;
    106. };
    107. ArkUI_AnimateOption *option = OH_ArkUI_AnimateOption_Create();
    108. OH_ArkUI_AnimateOption_SetDuration(option, 2000);
    109. OH_ArkUI_AnimateOption_SetTempo(option, 1.1);
    110. OH_ArkUI_AnimateOption_SetCurve(option, ARKUI_CURVE_EASE);
    111. OH_ArkUI_AnimateOption_SetDelay(option, 20);
    112. OH_ArkUI_AnimateOption_SetIterations(option, 1);
    113. OH_ArkUI_AnimateOption_SetPlayMode(option, ARKUI_ANIMATION_PLAY_MODE_REVERSE);
    114. ArkUI_ExpectedFrameRateRange *range = new ArkUI_ExpectedFrameRateRange;
    115. range->min = 10;
    116. range->max = 120;
    117. range->expected = 60;
    118. OH_ArkUI_AnimateOption_SetExpectedFrameRateRange(option, range);
    119. animateApi->animateTo(context, option, update, completeCallback);
    120. nodeAPI->setAttribute(Custom, NODE_WIDTH, &itemWidth);
    121. nodeAPI->setAttribute(Custom, NODE_HEIGHT, &itemHeight);
    122. nodeAPI->addChild(column, text);
    123. nodeAPI->addChild(column, Custom);
    124. nodeAPI->addChild(scroll, column);
    125. return scroll;
    126. }
    127. napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
    128. size_t argc = 2;
    129. napi_value args[2] = {nullptr, nullptr};
    130. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    131. auto *nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
    132. OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
    133. ArkUI_NodeHandle testNode = nullptr;
    134. if (nodeAPI != nullptr) {
    135. // 获取ets侧传入的context。
    136. ArkUI_ContextHandle context = nullptr;
    137. // 通过code判断是否获取成功。
    138. auto code = OH_ArkUI_GetContextFromNapiValue(env, args[1], &context);
    139. if (code != ARKUI_ERROR_CODE_NO_ERROR) {
    140. return nullptr;
    141. }
    142. testNode = testRenderNode2(nodeAPI, context);
    143. }
    144. NativeEntry::GetInstance()->SetRootNode(testNode);
    145. return nullptr;
    146. }

混排挂载原生组件与渲染节点

从API version 22开始,开发者可以高效地混排挂载原生组件与渲染节点。具体操作为:获取原生组件对应的渲染节点,并将其挂载至非原生组件的渲染节点下,从而实现原生组件的渲染节点与非原生组件的渲染节点混排。

进行混排挂载前,需要对原生组件进行接纳操作。父节点接纳目标子节点后,子节点会成为父节点的附属节点,只有附属节点能够获取渲染节点,并将这个渲染节点挂载至渲染节点树的其他位置上。

接纳子节点为附属节点

满足以下条件的节点,可以作为OH_ArkUI_NativeModule_AdoptChild接口中的父节点接纳其他节点:

  1. 父节点是C-API侧创建的命令式节点。
  2. 父节点是ArkTS侧创建的命令式节点。

满足以下条件的节点,可以作为OH_ArkUI_NativeModule_AdoptChild接口中的子节点被其他父节点接纳:

  1. 子节点是C-API侧创建的命令式节点。
  2. 子节点是ArkTS侧创建的命令式节点。
  3. 子节点是BuilderNode下的根节点。

子节点被接纳为附属节点后,不允许再作为常规子节点挂载至其他节点,否则会抛出相应的错误码。但允许该子节点被其他父节点再次接纳,此时该子节点将会成为其他父节点的新附属节点。被接纳的子节点不是其父节点的真实子节点,不在子组件查询接口的查询范围,也不支持像常规子节点那样被操作,同时不接受父节点的测量布局和事件传递,仅接收父节点的生命周期传递。

获取附属节点的渲染节点

节点处于被接纳的附属节点状态下,允许调用OH_ArkUI_RenderNodeUtils_GetRenderNode获取它对应的RenderNode。

调用ArkUI_NativeNodeAPI_1disposeNode接口主动销毁父节点时,需要额外调用OH_ArkUI_RenderNodeUtils_DisposeNode释放该渲染节点,否则会发生内存泄漏。

操作来自附属节点的渲染节点

从被接纳的附属节点中获取渲染节点后,即可使用该渲染节点进行布局,约束与限制如下:

  1. 将来自附属节点的渲染节点挂载至其他渲染节点下。

    来自附属节点的渲染节点只能作为子节点挂载至其他渲染节点下,或者从其他渲染节点下取消挂载,除此之外的任何操作都会执行失败并返回错误码。完成渲染节点挂载后,附属节点将会被绘制在该渲染节点对应的目标位置上。

  2. 附属节点的渲染节点依赖离屏挂载状态。

    如果该附属节点被它的父节点调用OH_ArkUI_NativeModule_RemoveAdoptedChild接口取消离屏挂载状态,那么该渲染节点也会随之一同从渲染节点树上被移除。

  3. 来自附属节点的渲染节点,如果它对应的附属节点已不处于离屏挂载状态,不允许重新将它挂载至其他渲染节点上。

创建并接纳Web组件以实现混排挂载

在进行如下代码开发前,请参考接入ArkTS页面,创建前置工程。

完整示例请参考native_render_node_sample

  1. NDK初始化组件环境,并创建对应的渲染节点根节点。

    收起
    自动换行
    深色代码主题
    复制
    1. std::shared_ptr<ArkUIBaseNode> custom_ = nullptr;
    2. std::shared_ptr<ArkUIRenderNode> render_ = nullptr;
    3. std::shared_ptr<ArkUIBaseNode> testGetRenderNodeDemo()
    4. {
    5. auto scroll = std::make_shared<ArkUIScrollNode>();
    6. scroll->SetWidth(g_contentWidth);
    7. scroll->SetHeight(g_contentHeight);
    8. scroll->SetBackgroundColor(0xff00F100);
    9. auto column = std::make_shared<ArkUIColumnNode>();
    10. column->SetWidth(g_contentWidth);
    11. column->SetHeight(g_contentHeight);
    12. auto text = std::make_shared<ArkUITextNode>();
    13. text->SetTextContent("挂载从frameNode获取的renderNode示例,点击下方挂载按钮");
    14. text->SetWidth(g_num300);
    15. text->SetHeight(g_num100);
    16. auto Custom = std::make_shared<ArkUICustomNode>();
    17. Custom->SetWidth(g_contentWidth);
    18. Custom->SetHeight(g_num100);
    19. column->AddChild(text);
    20. column->AddChild(Custom);
    21. custom_ = Custom;
    22. // 布置可挂载环境,将renderNode作为Custom的根节点挂载。
    23. auto renderNode = std::make_shared<ArkUIRenderNode>();
    24. Custom->AddRenderNode(renderNode);
    25. renderNode->SetSize(g_num300, g_num300);
    26. render_ = renderNode;
    27. scroll->AddChild(column);
    28. return scroll;
    29. }
    30. napi_value CreateRenderNodeGetNodeExample(napi_env env, napi_callback_info info)
    31. {
    32. size_t argc = 2;
    33. napi_value args[2] = {nullptr, nullptr};
    34. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    35. // 获取ArkTS侧组件挂载点。
    36. ArkUI_NodeContentHandle contentHandle;
    37. int32_t result = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    38. if (result != ARKUI_ERROR_CODE_NO_ERROR) {
    39. return nullptr;
    40. }
    41. // 创建Native侧组件树根节点。
    42. auto scrollNode = std::make_shared<ArkUIScrollNode>();
    43. // 将Native侧组件树根节点挂载到UI主树上。
    44. result = OH_ArkUI_NodeContent_AddNode(contentHandle, scrollNode->GetHandle());
    45. if (result != ARKUI_ERROR_CODE_NO_ERROR) {
    46. OH_LOG_ERROR(LOG_APP, "OH_ArkUI_NodeContent_AddNode Failed %{public}d", result);
    47. return nullptr;
    48. }
    49. // 保存Native侧组件树。
    50. g_nodeMap[contentHandle] = scrollNode;
    51. auto rootNode = testGetRenderNodeDemo();
    52. scrollNode->AddChild(rootNode);
    53. return nullptr;
    54. }
  2. ArkTS侧创建节点并传递该节点至C-API。

    收起
    自动换行
    深色代码主题
    复制
    1. import { BuilderNode, FrameNode, NodeContent, NodeController, typeNode } from '@kit.ArkUI';
    2. import entry from 'libentry.so';
    3. import { webview } from '@kit.ArkWeb';
    4. // 定义传递参数的接口
    5. interface ParamsInterface {
    6. text: string;
    7. func: Function;
    8. }
    9. class MyNodeController extends NodeController {
    10. private imperativeNode: FrameNode | null = null;
    11. public rootNode: typeNode.Column |null = null;
    12. private buildNode: FrameNode | null = null;
    13. makeNode(uiContext: UIContext): FrameNode {
    14. this.rootNode = typeNode.createNode(uiContext, 'Column');
    15. this.imperativeNode = new FrameNode(uiContext);
    16. this.rootNode?.appendChild(this.imperativeNode);
    17. return this.rootNode;
    18. }
    19. adoptNode(uiContext:UIContext, message:string):void {
    20. let buildNode = new BuilderNode<[ParamsInterface]>(uiContext);
    21. // 创建节点树
    22. buildNode.build(wrapBuilder<[ParamsInterface]>(buildText), {
    23. text: message, func: () => {
    24. return 'FUNCTION';
    25. }
    26. }, { nestingBuilderSupported: true });
    27. this.buildNode = buildNode.getFrameNode();
    28. entry.adopt(buildNode);
    29. }
    30. removeAdoptedNode(uiContext:UIContext):void {
    31. entry.removeAdopt();
    32. }
    33. }
    34. @Builder
    35. function buildTextWithFunc(fun: Function) {
    36. Web({ src: 'https://www.example.com', controller: new webview.WebviewController() })
    37. }
    38. @Builder
    39. function buildText(params: ParamsInterface) {
    40. Column() {
    41. buildTextWithFunc(params.func)
    42. }
    43. }
    44. @Component
    45. struct CAPIComponent {
    46. private rootSlot = new NodeContent();
    47. aboutToAppear(): void {
    48. entry.createRenderNodeGetNodeExample(this.rootSlot, this.getUIContext())
    49. }
    50. aboutToDisappear(): void {
    51. // 页面销毁前释放已创建的Native组件。
    52. entry.disposeNodeTree(this.rootSlot)
    53. }
    54. build() {
    55. Column() {
    56. // Native组件挂载点。
    57. ContentSlot(this.rootSlot)
    58. }
    59. }
    60. }
    61. @Entry
    62. @Component
    63. struct Index {
    64. @State isShow: boolean = false;
    65. @State isAdopt: boolean = false;
    66. @State message: string = 'CreateNodeTree';
    67. @State adoptmsg: string = 'adopt web component';
    68. private myNodeController: MyNodeController = new MyNodeController();
    69. build() {
    70. Flex() {
    71. Column() {
    72. Text('create CustomDrawNode,')
    73. .fontSize(18)
    74. .fontWeight(FontWeight.Bold)
    75. Button(this.message)
    76. .onClick(() => {
    77. this.isShow = !this.isShow;
    78. })
    79. if (this.isShow) {
    80. CAPIComponent()
    81. Button(this.adoptmsg)
    82. .onClick(() => {
    83. if (this.isAdopt) {
    84. this.myNodeController.removeAdoptedNode(this.getUIContext());
    85. this.adoptmsg = 'adopt web component';
    86. } else {
    87. this.myNodeController.adoptNode(this.getUIContext(),this.message);
    88. this.adoptmsg = 'remove adopt web';
    89. }
    90. this.isAdopt = !this.isAdopt;
    91. })
    92. NodeContainer(this.myNodeController)
    93. }
    94. }.width('100%')
    95. }.width('100%')
    96. }
    97. }
  3. C-API侧获取该节点,接纳节点并获取对应的渲染节点。

    收起
    自动换行
    深色代码主题
    复制
    1. napi_value Adopt(napi_env env, napi_callback_info info)
    2. {
    3. size_t argc = 1;
    4. napi_value args[1] = {nullptr};
    5. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    6. // 获取ArkTS侧组件挂载点。
    7. int32_t result = OH_ArkUI_GetNodeHandleFromNapiValue(env, args[0], &nodeHandle_);
    8. if (result != ARKUI_ERROR_CODE_NO_ERROR) {
    9. return nullptr;
    10. }
    11. result = OH_ArkUI_NativeModule_AdoptChild(custom_->GetHandle(), nodeHandle_);
    12. OH_ArkUI_RenderNodeUtils_GetRenderNode(nodeHandle_, &renderHandle_);
    13. OH_ArkUI_RenderNodeUtils_AddChild(render_->GetHandle(), renderHandle_);
    14. return nullptr;
    15. }
  4. C-API侧解除已被接纳节点的接纳状态,释放其对应的渲染节点。

    收起
    自动换行
    深色代码主题
    复制
    1. napi_value RemoveAdopt(napi_env env, napi_callback_info info)
    2. {
    3. OH_ArkUI_NativeModule_RemoveAdoptedChild(custom_->GetHandle(), nodeHandle_);
    4. // 解除节点的接纳状态后,需要额外调用OH_ArkUI_RenderNodeUtils_DisposeNode释放对应的渲染节点,否则会导致内存泄漏。
    5. OH_ArkUI_RenderNodeUtils_DisposeNode(renderHandle_);
    6. nodeHandle_ = nullptr;
    7. renderHandle_ = nullptr;
    8. return nullptr;
    9. }
搜索
请输入您想要搜索的关键词