马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
概述
XComponent组件作为一种渲染组件,通常用于满意开辟者较为复杂的自界说渲染需求,比方相机预览流的显示和游戏画面的渲染。其可通过指定其type字段来实现不同的功能,主要有两个“surface”和“component”字段可供选择。对于“surface”类型,开辟者可将相关数据传入XComponent单独拥有的“NativeWindow”来渲染画面。对于“component”类型,通常用于在XComponent内部执行非UI逻辑以实现动态加载显示内容的目标。
XComponent设置为“surface“类型时,其可以和其他组件一起进行布局和渲染,同时XComponent又拥有单独的“NativeWindow“,可以为开辟者在native侧提供NativeWindow用来创建EGL/OpenGLES情况,进而使用尺度的OpenGL ES开辟。除此之外,媒体相关应用(视频、相机等)也可以将相关数据写入XComponent所提供的NativeWindow,从而呈现相应画面。
目前XComponent组件在type设置为“surface”时主要有两个应用场景。一个是Native XComponent场景,是在native层获取Native XComponent实例,在native侧注册XComponent的生命周期回调,以及触摸、鼠标、按键等事件回调。另一个是ArkTS XComponent场景,是在ArkTS侧获取SurfaceId,生命周期回调、触摸、鼠标、按键等事件回调等均在ArkTS侧触发。
surface类型
Native XComponent场景
在XComponent组件构造函数的libraryname中界说需要加载的动态库,而后应用就可以在Native层获取Native XComponent实例,其是XComponent组件提供在Native层的实例,可作为ArkTS层和Native层XComponent绑定的桥梁。XComponent所提供的NDK接口都依靠于该实例。接口能力包罗获取NativeWindow实例、获取XComponent的布局/事件信息、注册XComponent的生命周期回调、注册XComponent的触摸、鼠标、按键等事件回调。针对Native XComponent,主要的开辟场景如下:
- 使用Native XComponent提供的接口注册XComponent的生命周期和事件回调。
- 在这些回调中进行初始化情况、获取当前状态、相应各类事件的开辟。
- 使用NativeWindow和EGL接口开辟自界说绘制内容以及申请和提交Buffer到图形队列。
接口说明
接口名形貌OH_NativeXComponent_GetXComponentId(OH_NativeXComponent* component, char* id, uint64_t* size)获取XComponent的id。OH_NativeXComponent_GetXComponentSize(OH_NativeXComponent* component, const void* window, uint64_t* width, uint64_t* height)获取XComponent持有的surface的大小。OH_NativeXComponent_GetXComponentOffset(OH_NativeXComponent* component, const void* window, double* x, double* y)获取XComponent持有的surface相对其父组件左顶点的偏移量。OH_NativeXComponent_GetTouchEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_TouchEvent* touchEvent)获取由XComponent触发的触摸事件。touchEvent内的详细属性值可参考OH_NativeXComponent_TouchEvent。OH_NativeXComponent_GetTouchPointToolType(OH_NativeXComponent* component, uint32_t pointIndex, OH_NativeXComponent_TouchPointToolType* toolType)获取XComponent触摸点的工具类型。OH_NativeXComponent_GetTouchPointTiltX(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltX)获取XComponent触摸点处相对X轴的倾斜角度。OH_NativeXComponent_GetTouchPointTiltY(OH_NativeXComponent* component, uint32_t pointIndex, float* tiltY)获取XComponent触摸点处相对Y轴的倾斜角度。OH_NativeXComponent_GetMouseEvent(OH_NativeXComponent* component, const void* window, OH_NativeXComponent_MouseEvent* mouseEvent)获取由XComponent触发的鼠标事件。OH_NativeXComponent_RegisterCallback(OH_NativeXComponent* component, OH_NativeXComponent_Callback* callback)为此OH_NativeXComponent实例注册生命周期和触摸事件回调。OH_NativeXComponent_RegisterMouseEventCallback(OH_NativeXComponent* component, OH_NativeXComponent_MouseEvent_Callback* callback)为此OH_NativeXComponent实例注册鼠标事件回调。OH_NativeXComponent_RegisterFocusEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window))为此OH_NativeXComponent实例注册获得核心事件回调。OH_NativeXComponent_RegisterKeyEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window))为此OH_NativeXComponent实例注册按键事件回调。OH_NativeXComponent_RegisterBlurEventCallback(OH_NativeXComponent* component, void (*callback)(OH_NativeXComponent* component, void* window))为此OH_NativeXComponent实例注册失去核心事件回调。OH_NativeXComponent_GetKeyEvent(OH_NativeXComponent* component, OH_NativeXComponent_KeyEvent** keyEvent)获取由XComponent触发的按键事件。OH_NativeXComponent_GetKeyEventAction(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyAction* action)获取按键事件的动作。OH_NativeXComponent_GetKeyEventCode(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_KeyCode* code)获取按键事件的键码值。OH_NativeXComponent_GetKeyEventSourceType(OH_NativeXComponent_KeyEvent* keyEvent, OH_NativeXComponent_EventSourceType* sourceType)获取按键事件的输入源类型。OH_NativeXComponent_GetKeyEventDeviceId(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* deviceId)获取按键事件的装备ID。OH_NativeXComponent_GetKeyEventTimestamp(OH_NativeXComponent_KeyEvent* keyEvent, int64_t* timestamp)获取按键事件的时间戳。 说明
上述接口不支持跨线程访问。
开辟步骤
以下步骤形貌了如何使用XComponent组件调用Node-API接口来创建EGL/GLES情况,实现在主页面绘制图形,并可以改变图形的颜色。
ArkTS XComponent场景
与Native XComponent不同,ArkTS XComponent不再需要libraryname参数。通过在ArkTS侧获取SurfaceId,布局信息、生命周期回调、触摸、鼠标、按键等事件回调等均在ArkTS侧触发,按需传递到Native侧进行处理。主要开辟场景如下:
- 基于ArkTS侧获取的SurfaceId,在Native侧调用OH_NativeWindow_CreateNativeWindowFromSurfaceId接口创建出NativeWindow实例。
- 使用NativeWindow和EGL接口开辟自界说绘制内容以及申请和提交Buffer到图形队列。
- ArkTS侧获取生命周期、事件等信息传递到Native侧处理。
接口说明
ArkTS侧的XComponentController
接口名形貌getXComponentSurfaceId(): string获取XComponent对应Surface的ID。onSurfaceCreated(surfaceId: string): void当XComponent持有的Surface创建后进行该回调。onSurfaceChanged(surfaceId: string, rect: SurfaceRect): void当XComponent持有的Surface大小改变后(包罗首次创建时的大小改变)进行该回调。onSurfaceDestroyed(surfaceId: string): void当XComponent持有的Surface烧毁后进行该回调。 Native侧
接口名形貌int32_t OH_NativeWindow_CreateNativeWindowFromSurfaceId (uint64_t surfaceId, OHNativeWindow **window )通过surfaceId创建对应的OHNativeWindow。void OH_NativeWindow_DestroyNativeWindow (OHNativeWindow* window)将OHNativeWindow对象的引用计数减1,当引用计数为0的时候,该OHNativeWindow对象会被析构掉。 开辟步骤
以下步骤形貌了如何使用XComponent组件在ArkTS侧传入Surfaceid,在native侧创建NativeWindow实例,然后创建EGL/GLES情况,实现在主页面绘制图形,并可以改变图形的颜色。
- 在界面中界说XComponent。
- @Entry
- @Component
- struct Index {
- @State message: string = 'Hello World'
- xComponentContext: object | undefined = undefined;
- xComponentAttrs: XComponentAttrs = {
- id: 'xcomponentId',
- type: XComponentType.SURFACE,
- libraryname: 'nativerender'
- }
- build() {
- Row() {
- // ...
- // 在xxx.ets 中定义 XComponent
- XComponent(this.xComponentAttrs)
- .focusable(true) // 可响应键盘事件
- .onLoad((xComponentContext) => {
- this.xComponentContext = xComponentContext;
- })
- .onDestroy(() => {
- console.log("onDestroy");
- })
- // ...
- }
- .height('100%')
- }
- }
-
- interface XComponentAttrs {
- id: string;
- type: number;
- libraryname: string;
- }
复制代码 - Node-API模块注册。
- // 在napi_init.cpp文件中,Init方法注册接口函数,从而将封装的C++方法传递出来,供ArkTS侧调用
- EXTERN_C_START
- static napi_value Init(napi_env env, napi_value exports)
- {
- // ...
- // 向ArkTS侧暴露接口getContext()
- napi_property_descriptor desc[] = {
- { "getContext", nullptr, PluginManager::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr }
- };
- if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed");
- return nullptr;
- }
- // 方法内检查环境变量是否包含XComponent组件实例,若实例存在注册绘制相关接口
- PluginManager::GetInstance()->Export(env, exports);
- return exports;
- }
- EXTERN_C_END
- // 编写接口的描述信息,根据实际需要可以修改对应参数
- static napi_module nativerenderModule = {
- .nm_version = 1,
- .nm_flags = 0,
- .nm_filename = nullptr,
- // 入口函数
- .nm_register_func = Init,// 指定加载对应模块时的回调函数
- // 模块名称
- .nm_modname = "nativerender", // 指定模块名称,对于XComponent相关开发,这个名称必须和ArkTS侧XComponent中libraryname的值保持一致
- .nm_priv = ((void *)0),
- .reserved = { 0 }
- };
- // __attribute__((constructor))修饰的方法由系统自动调用,使用Node-API接口napi_module_register()传入模块描述信息进行模块注册
- extern "C" __attribute__((constructor)) void RegisterModule(void)
- {
- napi_module_register(&nativerenderModule);
- }
- // 使用Node-API中的napi_define_properties方法,向ArkTS侧暴露drawPattern()方法,在ArkTS侧调用drawPattern()来绘制内容。
- void PluginRender::Export(napi_env env, napi_value exports)
- {
- // ...
- // 将接口函数注册为ArkTS侧接口drawPattern
- napi_property_descriptor desc[] = {
- { "drawPattern", nullptr, PluginRender::NapiDrawPattern, nullptr, nullptr, nullptr, napi_default, nullptr }
- };
- if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed");
- }
- }
复制代码 - 上述注册的六个函数在native侧详细实现。
- // 定义一个函数OnSurfaceCreatedCB(),封装初始化环境与绘制背景
- void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
- {
- // ...
- // 获取XComponent的id,即ArkTS侧XComponent组件构造中的id参数
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
- "OnSurfaceCreatedCB: Unable to get XComponent id");
- return;
- }
- // 初始化环境与绘制背景
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- uint64_t width;
- uint64_t height;
- // 获取XComponent拥有的surface的大小
- int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
- if ((xSize == OH_NativeXComponent_RESULT_SUCCESS) && (render != nullptr)) {
- if (render->eglCore_->EglContextInit(window, width, height)) {
- render->eglCore_->Background();
- }
- }
- }
- // 定义一个函数OnSurfaceChangedCB()
- void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window)
- {
- // ...
- // 获取XComponent的id
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
- "OnSurfaceChangedCB: Unable to get XComponent id");
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render != nullptr) {
- // 封装OnSurfaceChanged方法
- render->OnSurfaceChanged(component, window);
- }
- }
- // 定义一个函数OnSurfaceDestroyedCB(),将PluginRender类内释放资源的方法Release()封装在其中
- void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
- {
- // ...
- // 获取XComponent的id
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
- "OnSurfaceDestroyedCB: Unable to get XComponent id");
- return;
- }
- std::string id(idStr);
- // 释放资源
- PluginRender::Release(id);
- }
- // 定义一个函数DispatchTouchEventCB(),响应触摸事件时触发该回调
- void DispatchTouchEventCB(OH_NativeXComponent *component, void *window)
- {
- // ...
- // 获取XComponent的id
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
- "DispatchTouchEventCB: Unable to get XComponent id");
- return;
- }
- std::string id(idStr);
- PluginRender *render = PluginRender::GetInstance(id);
- if (render != nullptr) {
- // 封装OnTouchEvent方法
- render->OnTouchEvent(component, window);
- }
- }
- // 定义一个函数DispatchMouseEventCB(),响应鼠标事件时触发该回调
- void DispatchMouseEventCB(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchMouseEventCB");
- int32_t ret;
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
- if (ret != OH_NativeXComponent_RESULT_SUCCESS) {
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render) {
- // 封装OnMouseEvent方法
- render->OnMouseEvent(component, window);
- }
- }
- // 定义一个函数DispatchHoverEventCB(),响应鼠标悬停事件时触发该回调
- void DispatchHoverEventCB(OH_NativeXComponent *component, bool isHover) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchHoverEventCB");
- int32_t ret;
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
- if (ret != OH_NativeXComponent_RESULT_SUCCESS) {
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render) {
- // 封装OnHoverEvent方法
- render->OnHoverEvent(component, isHover);
- }
- }
- // 定义一个函数OnFocusEventCB(),响应获焦事件时触发该回调
- void OnFocusEventCB(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnFocusEventCB");
- int32_t ret;
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
- if (ret != OH_NativeXComponent_RESULT_SUCCESS) {
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render) {
- // 封装OnFocusEvent方法
- render->OnFocusEvent(component, window);
- }
- }
- // 定义一个函数OnBlurEventCB(),响应失去焦点事件时触发该回调
- void OnBlurEventCB(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnBlurEventCB");
- int32_t ret;
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
- if (ret != OH_NativeXComponent_RESULT_SUCCESS) {
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render) {
- // 封装OnBlurEvent方法
- render->OnBlurEvent(component, window);
- }
- }
- // 定义一个函数OnKeyEventCB(),响应按键事件时触发该回调
- void OnKeyEventCB(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnKeyEventCB");
- int32_t ret;
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
- if (ret != OH_NativeXComponent_RESULT_SUCCESS) {
- return;
- }
- std::string id(idStr);
- auto render = PluginRender::GetInstance(id);
- if (render) {
- // 封装OnKeyEvent方法
- render->OnKeyEvent(component, window);
- }
- }
- // 定义一个OnSurfaceChanged()方法
- void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window)
- {
- // ...
- std::string id(idStr);
- PluginRender* render = PluginRender::GetInstance(id);
- double offsetX;
- double offsetY;
- // 获取XComponent持有的surface相对其父组件左顶点的偏移量
- OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY);
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OH_NativeXComponent_GetXComponentOffset",
- "offsetX = %{public}lf, offsetY = %{public}lf", offsetX, offsetY);
- uint64_t width;
- uint64_t height;
- OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
- if (render != nullptr) {
- render->eglCore_->UpdateSize(width, height);
- }
- }
- // 定义一个OnTouchEvent()方法
- void PluginRender::OnTouchEvent(OH_NativeXComponent* component, void* window)
- {
- // ...
- OH_NativeXComponent_TouchEvent touchEvent;
- // 获取由XComponent触发的触摸事件
- OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent);
- // 获取XComponent触摸点相对于XComponent组件左边缘的坐标x和相对于XComponent组件上边缘的坐标y
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent",
- "touch info: x = %{public}lf, y = %{public}lf", touchEvent.x, touchEvent.y);
- // 获取XComponent触摸点相对于XComponent所在应用窗口左上角的x坐标和相对于XComponent所在应用窗口左上角的y坐标
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent",
- "touch info: screenX = %{public}lf, screenY = %{public}lf", touchEvent.screenX, touchEvent.screenY);
- std::string id(idStr);
- PluginRender* render = PluginRender::GetInstance(id);
- if (render != nullptr && touchEvent.type == OH_NativeXComponent_TouchEventType::OH_NativeXComponent_UP) {
- render->eglCore_->ChangeColor();
- hasChangeColor_ = 1;
- }
- float tiltX = 0.0f;
- float tiltY = 0.0f;
- OH_NativeXComponent_TouchPointToolType toolType =
- OH_NativeXComponent_TouchPointToolType::OH_NativeXComponent_TOOL_TYPE_UNKNOWN;
- // 获取XComponent触摸点的工具类型
- OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
- // 获取XComponent触摸点处相对X轴的倾斜角度
- OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX);
- // 获取XComponent触摸点处相对Y轴的倾斜角度
- OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY);
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "OnTouchEvent",
- "touch info: toolType = %{public}d, tiltX = %{public}lf, tiltY = %{public}lf", toolType, tiltX, tiltY);
- }
- // 定义一个OnMouseEvent()方法
- void PluginRender::OnMouseEvent(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnMouseEvent");
- OH_NativeXComponent_MouseEvent mouseEvent;
- // 获取由XComponent触发的鼠标事件
- int32_t ret = OH_NativeXComponent_GetMouseEvent(component, window, &mouseEvent);
- if (ret == OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "MouseEvent Info: x = %{public}f, y = %{public}f, action = %{public}d, button = %{public}d", mouseEvent.x, mouseEvent.y, mouseEvent.action, mouseEvent.button);
- } else {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetMouseEvent error");
- }
- }
- // 定义一个OnMouseEvent()方法
- void PluginRender::OnKeyEvent(OH_NativeXComponent *component, void *window) {
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "OnKeyEvent");
- OH_NativeXComponent_KeyEvent *keyEvent = nullptr;
- // 获取由XComponent触发的按键事件。
- if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) {
- OH_NativeXComponent_KeyAction action;
- // 获取按键事件的动作
- OH_NativeXComponent_GetKeyEventAction(keyEvent, &action);
- OH_NativeXComponent_KeyCode code;
- // 获取按键事件的键码值
- OH_NativeXComponent_GetKeyEventCode(keyEvent, &code);
- OH_NativeXComponent_EventSourceType sourceType;
- // 获取按键事件的输入源类型
- OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType);
- int64_t deviceId;
- // 获取按键事件的设备ID
- OH_NativeXComponent_GetKeyEventDeviceId(keyEvent, &deviceId);
- int64_t timeStamp;
- // 获取按键事件的时间戳
- OH_NativeXComponent_GetKeyEventTimestamp(keyEvent, &timeStamp);
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "KeyEvent Info: action=%{public}d, code=%{public}d, sourceType=%{public}d, deviceId=%{public}ld, timeStamp=%{public}ld", action, code, sourceType, deviceId, timeStamp);
- } else {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "GetKeyEvent error");
- }
- }
复制代码 - 配置详细的CMakeLists,使用CMake工具链将C++源代码编译成动态链接库文件。
- void PluginRender::RegisterCallback(OH_NativeXComponent *NativeXComponent) {
- // 设置组件创建事件的回调函数,组件创建时触发相关操作,初始化环境与绘制背景
- renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
- // 设置组件改变事件的回调函数,组件改变时触发相关操作
- renderCallback_.OnSurfaceChanged = OnSurfaceChangedCB;
- // 设置组件销毁事件的回调函数,组件销毁时触发相关操作,释放申请的资源
- renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
- // 设置触摸事件的回调函数,在触摸事件触发时调用Node-API接口函数,从而调用原C++方法
- renderCallback_.DispatchTouchEvent = DispatchTouchEventCB;
- // 将OH_NativeXComponent_Callback注册给NativeXComponent
- OH_NativeXComponent_RegisterCallback(NativeXComponent, &renderCallback_);
- // 设置鼠标事件的回调函数,在触摸事件触发时调用Node-API接口函数,从而调用原C++方法
- mouseCallback_.DispatchMouseEvent = DispatchMouseEventCB;
- // 设置鼠标悬停事件的回调函数,在触摸事件触发时调用Node-API接口函数,从而调用原C++方法
- mouseCallback_.DispatchHoverEvent = DispatchHoverEventCB;
- // 将OH_NativeXComponent_MouseEvent_Callback注册给NativeXComponent
- OH_NativeXComponent_RegisterMouseEventCallback(NativeXComponent, &mouseCallback_);
- // 将OnFocusEventCB方法注册给NativeXComponent
- OH_NativeXComponent_RegisterFocusEventCallback(NativeXComponent, OnFocusEventCB);
- // 将OnKeyEventCB方法注册给NativeXComponent
- OH_NativeXComponent_RegisterKeyEventCallback(NativeXComponent, OnKeyEventCB);
- // 将OnBlurEventCB方法注册给 NativeXComponent
- OH_NativeXComponent_RegisterBlurEventCallback(NativeXComponent, OnBlurEventCB);
- }
复制代码 component类型
XComponent设置为component类型时通常用于在XComponent内部执行非UI逻辑以实现动态加载显示内容的目标。
说明
type为"component"时,XComponent作为容器,子组件沿垂直方向布局:
- 垂直方向上对齐格式:FlexAlign.Start
- 程度方向上对齐格式:FlexAlign.Center
不支持所有的事件相应。
布局方式更改和事件相应均可通过挂载子组件来设置。
内部所写的非UI逻辑需要封装在一个或多个函数内。
- napi_value PluginRender::NapiDrawPattern(napi_env env, napi_callback_info info)
- {
- // ...
- // 获取环境变量参数
- napi_value thisArg;
- if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_get_cb_info fail");
- return nullptr;
- }
-
- // 获取环境变量中XComponent实例
- napi_value exportInstance;
- if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
- "NapiDrawPattern: napi_get_named_property fail");
- return nullptr;
- }
-
- // 通过napi_unwrap接口,获取XComponent的实例指针
- OH_NativeXComponent *NativeXComponent = nullptr;
- if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&NativeXComponent)) != napi_ok) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_unwrap fail");
- return nullptr;
- }
-
- // 获取XComponent实例的id
- char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
- uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
- if (OH_NativeXComponent_GetXComponentId(NativeXComponent, idStr, &idSize) != OH_NativeXComponent_RESULT_SUCCESS) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
- "NapiDrawPattern: Unable to get XComponent id");
- return nullptr;
- }
-
- std::string id(idStr);
- PluginRender *render = PluginRender::GetInstance(id);
- if (render) {
- // 调用绘制方法
- render->eglCore_->Draw();
- OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglCore_->Draw() executed");
- }
- return nullptr;
- }
复制代码

生命周期说明
开辟者在ArkTS侧使用如下代码即可用XComponent组件进利用用EGL/OpenGLES渲染的开辟。
- void EGLCore::UpdateSize(int width, int height)
- {
- width_ = width;
- height_ = height;
- if (width_ > 0) {
- // 计算绘制矩形宽度百分比
- width_Percent_ = FIFTY_PERCENT * height_ / width_;
- }
- }
- bool EGLCore::EglContextInit(void *window, int width, int height)
- {
- // ...
- UpdateSize(width, height);
- eglWindow_ = static_cast<EGLNativeWindowType>(window);
- // 初始化display
- eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (eglDisplay_ == EGL_NO_DISPLAY) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display");
- return false;
- }
- // 初始化EGL
- EGLint majorVersion;
- EGLint minorVersion;
- if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore",
- "eglInitialize: unable to get initialize EGL display");
- return false;
- }
- // 选择配置
- const EGLint maxConfigSize = 1;
- EGLint numConfigs;
- if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) {
- OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs");
- return false;
- }
- // 创建环境
- return CreateEnvironment();
- }
复制代码 onLoad事件
触发时刻:XComponent准备好surface后触发。
参数context:其上面挂载了暴露在模块上的Native方法,使用方法雷同于使用 import context from "libnativerender.so" 直接加载模块后获得的context实例。
时序:
Native XComponent场景:
onLoad事件的触发和surface相关,其和Native侧的OnSurfaceCreated的时序如下图:
ArkTS XComponent场景:
onLoad事件的触发和surface相关,其和ArkTS侧的OnSurfaceCreated的时序如下图:
onDestroy事件
触发时刻:XComponent组件被烧毁时触发,与一般ArkUI的组件烧毁机遇同等。
时序:
Native XComponent场景:
onDestroy事件的触发和surface相关,其和Native侧的OnSurfaceDestroyed的时序如下图:
ArkTS XComponent场景:
onDestroy事件的触发和surface相关,其和ArkTS侧的OnSurfaceDestroyed的时序如下图:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |