鸿蒙开发 自定义渲染 (XComponent)

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之XComponent组件 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之XComponent组件。 阅读详情
往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)

1.嵌入式开发适不适合做鸿蒙南向开发?一文带你了解

2.鸿蒙众多岗位需求突增!该如何选择?

3.分享一场鸿蒙开发岗位面试经历~

4.待更新中……

概述

XComponent组件作为一种渲染组件,可用于EGL/OpenGLES和媒体数据写入,通过使用XComponent独有的“ NativeWindow ”来渲染画面,通常用于满足开发者较为复杂的自定义渲染需求,例如相机预览流的显示和游戏画面的渲染。其可通过指定type字段来实现不同的渲染方式,分别为 XComponentType .SURFACE和XComponentType.TEXTURE。对于SURFACE类型,开发者将定制的绘制内容单独展示到屏幕上。对于TEXTURE类型,开发者将定制的绘制内容和XComponent组件的内容合成后展示到屏幕上。

目前XComponent组件主要有两个应用场景。一个是Native XComponent场景,在native层获取Native XComponent实例,在native侧注册XComponent的生命周期回调,以及触摸、鼠标、按键等事件回调。另一个是ArkTS XComponent场景,在ArkTS侧获取SurfaceId,生命周期回调、触摸、鼠标、按键等事件回调等均在ArkTS侧触发。

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销毁(onSurfaceDestroyed回调触发后)时会释放上述接口中获取的OH_NativeXComponent和window对象。如果在之后再次使用获取的这些对象有可能会导致出现使用野指针或空指针的崩溃问题,需要开发者避免。

开发步骤

以下步骤以SURFACE类型为例,描述了如何使用XComponent组件调用Node-API接口来创建EGL/GLES环境,实现在主页面绘制图形,并可以改变图形的颜色。1. 在界面中定义XComponent。

//接口声明
export default interface XComponentContext {
  drawPattern(): void;

  getStatus(): XComponentContextStatus;
};

type XComponentContextStatus = {
  hasDraw: boolean,
  hasChangeColor: boolean,
};
@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;
}

2. Node-API模块注册,具体使用请参考 Native 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");
    }
}

3. 注册XComponent事件回调,使用Node-API实现XComponent事件回调函数。
(1) 定义surface创建成功,发生改变,销毁和XComponent的touch事件回调接口。

//定义PluginRender类
class PluginRender {
public:
    explicit PluginRender(std::string& id);
    ~PluginRender()
    {
        if (eglCore_ != nullptr) {
            eglCore_->Release();
            delete eglCore_;
            eglCore_ = nullptr;
        }
    }
    static PluginRender* GetInstance(std::string& id);
    static void Release(std::string& id);
    static napi_value NapiDrawPattern(napi_env en
OpenHarmony实战开发-如何实现自定义绘制 (XComponent) XComponent组件作为一种绘制组件,通常用于满足开发者较为复杂的自定义绘制需求,例如相机预览流的显示和游戏画面的绘制。 阅读详情

相关推荐

鸿蒙开发基础 —— ArkUI 组件(自定义渲染 (XComponent))

XComponent组件作为一种渲染组件,可用于EGL/OpenGLES和媒体数据写入,通过使用XComponent独有的“ NativeWindow ”来渲染画面,通常用于满足开发者较为复杂的自定义渲染需求,例如相机预览流的显示和游戏画面的渲染。其可通过指定type字段来实现不同的渲染方式,分别为 XComponentType .SURFACE和XComponentType.TEXTURE。对于SURFACE类型,开发者将定制的绘制内容单独展示到屏幕上。

guangxishaoji的博客 1250

【鸿蒙基于API 13实战开发】—— ArkUI 组件(自定义渲染 (XComponent))

XComponent组件作为一种渲染组件,可用于EGL/OpenGLES和媒体数据写入,通过使用XComponent独有的“ NativeWindow ”来渲染画面,通常用于满足开发者较为复杂的自定义渲染需求,例如相机预览流的显示和游戏画面的渲染。其可通过指定type字段来实现不同的渲染方式,分别为 XComponentType .SURFACE和XComponentType.TEXTURE。对于SURFACE类型,开发者将定制的绘制内容单独展示到屏幕上。

shangkangba的博客 1294

鸿蒙5.0进阶开发:UI开发-自定义渲染 (XComponent)

XComponent组件作为一种渲染组件,可用于EGL/OpenGLES和媒体数据写入..........

AyomQAQ的博客 1272

HarmonyOS Next开发学习手册——自定义绘制 (XComponent)

开发者在ArkTS侧使用如下代码,即可用XComponent组件进行利用EGL/OpenGLES渲染的开发。id : 与XComponent组件为一一对应关系,不建议重复。通常开发者可以在native侧通过OH_NativeXComponent_GetXComponentId接口来获取对应的id从而绑定对应的XComponent。说明如果id重复,在native侧将无法对多个XComponent进行区分。

maniuT的博客 1991

HarmonyOS Next开发学习手册——添加组件(Native XComponent)

Native XComponent是XComponent组件提供在Native层的实例,可作为JS层和Native层XComponent绑定的桥梁。XComponent所提供的NDK接口都依赖于该实例。接口能力包括获取Native Window实例、获取XComponent的布局/事件信息、注册XComponent的生命周期回调、注册XComponent的触摸、鼠标、按键等事件回调。利用Native XComponent提供的接口注册XComponent的生命周期和事件回调。

maniuT的博客 1158

鸿蒙OpenHarmony【自定义渲染 (XComponent)】 ArkUI

XComponent组件作为一种渲染组件,可用于EGL/OpenGLES和媒体数据写入,通过使用XComponent独有的“[NativeWindow]”来渲染画面,通常用于满足开发者较为复杂的自定义渲染需求,例如相机预览流的显示和游戏画面的渲染。其可通过指定type字段来实现不同的渲染方式,分别为[XComponentType].SURFACE和XComponentType.TEXTURE。对于SURFACE类型,开发者将定制的绘制内容单独展示到屏幕上。对于TEXTURE类型,开发者将定制的绘制内容和XC

adsjgfjha123123的博客 1045

鸿蒙(HarmonyOS)应用开发实战——XComponent + Vsync 实现自定义动画

XComponent 提供了应用在 native 侧调用 OpenGLES 图形接口的能力,本文主要介绍如何配合 Vsync 事件,完成自定义动画。在这种实现方式下,自定义动画的绘制不在 UI 主线程中完成,即使主线程卡顿,动画效果也不会受影响。

CTrup的博客 929

OpenHarmony/HarmonyOS基础组件之XComponent

可用于EGL/OpenGLES和媒体数据写入,并显示在XComponent组件。

坚果的博客 1万+

Arm A-profile架构RAS系统设计:可靠性、可用性与可服务性解析

在计算机体系结构中,可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)是构建高可信系统的核心要素。RAS系统通过硬件错误检测、隔离和恢复机制,确保系统持续稳定运行。其技术原理包括ECC内存纠错、冗余执行单元和错误传播阻断等关键技术,可显著降低数据中心等关键业务场景的故障率。现代芯片设计中,Arm A-profile架构提供标准化的RAS框架,涵盖从内存子系统到计算单元的全方位错误管理。通过分层防御策略和统一错误记录格式,实现硬件错误可追溯、可修复。

weixin_30920853的博客 357

Win11下高效管理JDK1.8与JDK17双环境的实战指南

本文提供了一份在Windows 11系统上高效管理JDK 1.8与JDK 17双环境的实战指南。文章详细讲解了如何实现双版本切换,包括如何干净安装两个JDK、通过巧妙配置环境变量实现命令行一键切换,以及在不同IDE和构建工具中为项目独立配置JDK版本,旨在帮助Java开发者彻底解决版本冲突问题,提升开发效率。

ipfs8storage的博客 543

osgEarth添加线特征

部分关键代码: osgEarth::Annotation::FeatureNode* pathNode = 0; osgEarth::Symbology::Geometry* path = new osgEarth::Symbology::LineString(); Track*track = dynamic_cast<Track*>(entity->getProperty(PS_TRACK)); if (track == nullptr) { return; } st.

wb175208的专栏 2967

badusb详细制作教程(两种方式实现远控)

badusb是一种几乎可以突破任何杀毒软件和防火墙的设备,堪称渗透测试利器 文章目录前言一、什么是badusb?二,badusb的优点三,badusb是如何攻击的?badusb原理HID攻击漏洞产生原因三、准备步骤1.设备2,编辑器的安装与设置四,编写代码(重点)第一种: SEToolkit + badusb实现PowerShell注入攻击第二种:Cobalt Strike + badusb 实现PowerShell注入攻击五,烧录六,badusb有多强大攻击场景总结 BadUSB是《黑客军团》中

Ghost_system的博客 1万+

【无线通信】射频杂散(RF Spurious Emissions)

射频杂散(RF Spurious Emissions)是指在无线通信系统中,除了在指定频率范围内的预期信号之外,任何不需要的或非预期的射频信号。这些杂散信号可能会干扰其他通信系统,降低系统性能,并违反无线电通信法规。射频杂散通常包括谐波、次谐波、互调产物和其他非线性失真所产生的信号。

qq_38801607的博客 5424

YOLOv11改进前必看 - YAML模型配置文件详细解读(再也不用担心通道数不匹配) 附网络结构图

YOLOv11的模型配置文件在中,里面包含以及,本文以目标检测模型文件为例(其他文件完全一致),详细介绍一下YOLOv11模型文件中各参数的含义。

Limiiiing的博客 5310

在Windows10上安装WSL2

WSL2是微软提供的Windows子系统,允许在Windows 10和11上运行Linux环境,提供更好的性能和兼容性。安装WSL2需要启用WSL功能、更新系统、安装WSL2内核,并设置为默认版本。之后,可以通过Microsoft Store安装Linux发行版,并使用WSL命令启动和管理它们。

howard2005的专栏 5940

Arduino、ESP32驱动BMP390L数字大气压传感器(压力传感器)

BMP390L是一款博世新研发的工业级专用数字气压传感器,具有极高的温度稳定性、低漂移、低功耗。

不脱发的程序猿 2007

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: 鸿蒙开发 ArkUI 组件(视频播放 (Video))
下一篇: 鸿蒙开发 气泡提示 (Popup)
普通网友
博客等级 码龄2年 826粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值