添加输入框文本事件监听
===========

输入框包含多种交互行为，开发者可注册事件监听并获取状态。以下以多行文本输入框为例进行说明，单行文本输入框添加文本事件监听的步骤与此类似。

要实现实时搜索功能，可注册[NODE\_TEXT\_AREA\_ON\_CHANGE](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodeeventtype)事件，输入框文本发生变化时会收到通知，并能获取当前文本内容。

要实现文字过滤功能，可注册[NODE\_TEXT\_AREA\_ON\_WILL\_INSERT](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodeeventtype)事件，在文字即将插入前会收到通知，通过返回值控制文字是否插入。

要实现用户编辑文字前后页面布局的不同，可注册[NODE\_TEXT\_AREA\_ON\_EDIT\_CHANGE](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodeeventtype)事件，输入框编辑状态切换时会收到通知。

以下示例基于[接入ArkTS页面章节](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ndk-access-the-arkts-page)，说明如何监听输入框的事件及数据解析。

*   注册事件
    
    事件注册有统一接口，详情请参见[registerNodeEvent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkui-nativemodule-arkui-nativenodeapi-1#registernodeevent)。输入框支持的事件类型，请参见NativeNode组件支持的事件类型定义[ArkUI\_NodeEventType](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-node-h#arkui_nodeeventtype)，搜索前缀NODE\_TEXT\_AREA\_。
    
    ArkUI\_NodeHandle text = nodeApi->createNode(ARKUI\_NODE\_TEXT);
    ArkUI\_NumberValue textWidth\[\] = {{.f32 = 300}};
    ArkUI\_AttributeItem textWidthItem = {.value = textWidth, .size = 1};
    nodeApi->setAttribute(text, NODE\_WIDTH, &textWidthItem);
    // ···
    ArkUI\_NodeHandle selectionText = nodeApi->createNode(ARKUI\_NODE\_TEXT);
    ArkUI\_NumberValue selectionTextWidth\[\] = {{.f32 = 300}};
    ArkUI\_AttributeItem selectionTextWidthItem = {.value = selectionTextWidth, .size = 1};
    nodeApi->setAttribute(selectionText, NODE\_WIDTH, &selectionTextWidthItem);
    // ···
    const ArkUI\_AttributeItem \*attributeItem = nodeApi->getAttribute(textArea, NODE\_UNIQUE\_ID);
    auto id = attributeItem->value\[0\].i32;
    nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_CHANGE, id, text);
    nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_PASTE, id, text);
    nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_TEXT\_SELECTION\_CHANGE, id, selectionText);
    
*   注册事件回调
    
    事件回调注册有统一接口，详情请参见[registerNodeEventReceiver](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-arkui-nativemodule-arkui-nativenodeapi-1#registernodeeventreceiver)。
    
    nodeApi->registerNodeEventReceiver(\[\](ArkUI\_NodeEvent \*event) {
        ArkUI\_NodeEventType eventType = OH\_ArkUI\_NodeEvent\_GetEventType(event);
        ArkUI\_AttributeItem content;
        if (eventType == NODE\_TEXT\_AREA\_ON\_CHANGE || eventType == NODE\_TEXT\_AREA\_ON\_PASTE) {
            ArkUI\_StringAsyncEvent \*stringEvent = OH\_ArkUI\_NodeEvent\_GetStringAsyncEvent(event);
            content = {.string = stringEvent->pStr };
        } else if (eventType == NODE\_TEXT\_AREA\_ON\_TEXT\_SELECTION\_CHANGE) {
            ArkUI\_NodeComponentEvent \*componentEvent = OH\_ArkUI\_NodeEvent\_GetNodeComponentEvent(event);
            std::stringstream selectContent;
            selectContent << "start: " << componentEvent->data\[0\].i32 << " , end: " << componentEvent->data\[1\].i32;
            content = {.string = selectContent.str().c\_str() };
        } else {
            return;
        }
        ArkUI\_NodeHandle textNode = reinterpret\_cast<ArkUI\_NodeHandle>(OH\_ArkUI\_NodeEvent\_GetUserData(event));
        if (textNode) {
            ArkUI\_NativeNodeAPI\_1 \*nodeApi = reinterpret\_cast<ArkUI\_NativeNodeAPI\_1 \*>(
                OH\_ArkUI\_QueryModuleInterfaceByName(ARKUI\_NATIVE\_NODE, "ArkUI\_NativeNodeAPI\_1"));
            nodeApi->setAttribute(textNode, NODE\_TEXT\_CONTENT, &content);
        }
    });
    
*   完整示例
    
    本篇示例仅提供核心接口的调用方法，完整的示例工程请参考[TextAreaEventNDK](https://gitcode.com/HarmonyOS_Samples/guide-snippets/tree/master/ArkUISample/TextAreaEventNDK)。
    
    #include "manager.h"
    #include <sstream>
    #include <arkui/native\_interface.h>
    #include <arkui/styled\_string.h>
    #include <hilog/log.h>
    
    #define CUSTOM\_LOG\_TAG "manager"
    #define LOG\_ERROR(...) OH\_LOG\_Print(LOG\_APP, LOG\_ERROR, 0xD001400, CUSTOM\_LOG\_TAG, \_\_VA\_ARGS\_\_)
    #define LOG\_INFO(...) OH\_LOG\_Print(LOG\_APP, LOG\_INFO, 0xD001400, CUSTOM\_LOG\_TAG, \_\_VA\_ARGS\_\_)
    
    namespace ConstIde {
    const uint32\_t NUMBER\_0 = 0;
    const uint32\_t NUMBER\_1 = 1;
    constexpr const char \*K\_LOG\_DOMAIN = "Manager";
    } // namespace ConstIde
    
    Manager Manager::manager\_;
    ArkUI\_NativeNodeAPI\_1 \*Manager::nodeAPI\_ = reinterpret\_cast<ArkUI\_NativeNodeAPI\_1 \*>(
        OH\_ArkUI\_QueryModuleInterfaceByName(ARKUI\_NATIVE\_NODE, "ArkUI\_NativeNodeAPI\_1"));
    template <class MakeNodeFn>
    static napi\_value CreateNativeNode(napi\_env env, napi\_callback\_info info, const char \*who, MakeNodeFn makeNodeFn)
    {
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s BEGIN", who);
    
        if ((env == nullptr) || (info == nullptr)) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s env or info is null",
                         who);
            return nullptr;
        }
    
        size\_t argc = ConstIde::NUMBER\_1;
        napi\_value args\[ConstIde::NUMBER\_1\] = {nullptr};
        napi\_status st = napi\_get\_cb\_info(env, info, &argc, args, nullptr, nullptr);
        if (st != napi\_ok || argc < ConstIde::NUMBER\_1) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s napi\_get\_cb\_info failed",
                         who);
            return nullptr;
        }
    
        ArkUI\_NodeContentHandle nodeContentHandle = nullptr;
        OH\_ArkUI\_GetNodeContentFromNapiValue(env, args\[ConstIde::NUMBER\_0\], &nodeContentHandle);
        if (nodeContentHandle == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN,
                         "%{public}s nodeContentHandle is null", who);
            return nullptr;
        }
    
        OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s after GetNodeContent", who);
    
        // 可选：保留对 nodeAPI\_ 的健壮性检查（与你现有代码一致）
        if (Manager::nodeAPI\_ == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s nodeAPI\_ is null", who);
            return nullptr;
        }
    
        // 构建具体节点 & 挂载
        ArkUI\_NodeHandle page = makeNodeFn();
        if (page == nullptr) {
            OH\_LOG\_Print(LOG\_APP, LOG\_INFO, LOG\_PRINT\_DOMAIN, ConstIde::K\_LOG\_DOMAIN, "%{public}s makeNodeFn return null",
                         who);
            return nullptr;
        }
    
        OH\_ArkUI\_NodeContent\_AddNode(nodeContentHandle, page);
        return nullptr;
    }
    
    constexpr int32\_t NUM\_10 = 10;
    constexpr int32\_t NUM\_28 = 28;
    constexpr int32\_t NUM\_400 = 400;
    
    napi\_value Manager::CreateTextAreaNativeNode(napi\_env\_\_\* env, napi\_callback\_info\_\_\* info)
    {
        return CreateNativeNode(env, info, "CreateTextAreaNativeNode",
                                \[\]() -> ArkUI\_NodeHandle { return CreateTextAreaNativeNode(); });
    }
    
    ArkUI\_NodeHandle Manager::CreateTextAreaNativeNode()
    {
        ArkUI\_NativeNodeAPI\_1 \*nodeApi = Manager::nodeAPI\_;
    
        ArkUI\_NodeHandle column = nodeApi->createNode(ARKUI\_NODE\_COLUMN);
        ArkUI\_NumberValue colWidth\[\] = {{.f32 = 300}};
        ArkUI\_AttributeItem widthItem = {.value = colWidth, .size = 1};
        nodeApi->setAttribute(column, NODE\_WIDTH, &widthItem);
    
        ArkUI\_NodeHandle text = nodeApi->createNode(ARKUI\_NODE\_TEXT);
        ArkUI\_NumberValue textWidth\[\] = {{.f32 = 300}};
        ArkUI\_AttributeItem textWidthItem = {.value = textWidth, .size = 1};
        nodeApi->setAttribute(text, NODE\_WIDTH, &textWidthItem);
        ArkUI\_NumberValue textHeight\[\] = {{.f32 = 100}};
        ArkUI\_AttributeItem textHeightItem = {.value = textHeight, .size = 1};
        nodeApi->setAttribute(text, NODE\_HEIGHT, &textHeightItem);
        
        nodeApi->addChild(column, text);
        
        ArkUI\_NodeHandle selectionText = nodeApi->createNode(ARKUI\_NODE\_TEXT);
        ArkUI\_NumberValue selectionTextWidth\[\] = {{.f32 = 300}};
        ArkUI\_AttributeItem selectionTextWidthItem = {.value = selectionTextWidth, .size = 1};
        nodeApi->setAttribute(selectionText, NODE\_WIDTH, &selectionTextWidthItem);
        nodeApi->addChild(column, selectionText);
        ArkUI\_NodeHandle textArea = nodeApi->createNode(ARKUI\_NODE\_TEXT\_AREA);
        ArkUI\_NumberValue textAreaWidth\[\] = {{.f32 = 300}};
        ArkUI\_AttributeItem textAreaWidthItem = {.value = textAreaWidth, .size = 1};
        nodeApi->setAttribute(textArea, NODE\_WIDTH, &textAreaWidthItem);
    
        ArkUI\_NumberValue borderWidth\[\] = {{.f32 = 1}};
        ArkUI\_AttributeItem borderWidthItem = {.value = borderWidth, .size = 1};
        nodeApi->setAttribute(textArea, NODE\_BORDER\_WIDTH, &borderWidthItem);
    
        const ArkUI\_AttributeItem \*attributeItem = nodeApi->getAttribute(textArea, NODE\_UNIQUE\_ID);
        auto id = attributeItem->value\[0\].i32;
        nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_CHANGE, id, text);
        nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_PASTE, id, text);
        nodeApi->registerNodeEvent(textArea, NODE\_TEXT\_AREA\_ON\_TEXT\_SELECTION\_CHANGE, id, selectionText);
        TextAreaNodeEventReceiver(nodeApi);
        nodeApi->addChild(column, textArea);
        return column;
    }
    
    void Manager::TextAreaNodeEventReceiver(ArkUI\_NativeNodeAPI\_1\* nodeApi)
    {
        nodeApi->registerNodeEventReceiver(\[\](ArkUI\_NodeEvent \*event) {
            ArkUI\_NodeEventType eventType = OH\_ArkUI\_NodeEvent\_GetEventType(event);
            ArkUI\_AttributeItem content;
            if (eventType == NODE\_TEXT\_AREA\_ON\_CHANGE || eventType == NODE\_TEXT\_AREA\_ON\_PASTE) {
                ArkUI\_StringAsyncEvent \*stringEvent = OH\_ArkUI\_NodeEvent\_GetStringAsyncEvent(event);
                content = {.string = stringEvent->pStr };
            } else if (eventType == NODE\_TEXT\_AREA\_ON\_TEXT\_SELECTION\_CHANGE) {
                ArkUI\_NodeComponentEvent \*componentEvent = OH\_ArkUI\_NodeEvent\_GetNodeComponentEvent(event);
                std::stringstream selectContent;
                selectContent << "start: " << componentEvent->data\[0\].i32 << " , end: " << componentEvent->data\[1\].i32;
                content = {.string = selectContent.str().c\_str() };
            } else {
                return;
            }
            ArkUI\_NodeHandle textNode = reinterpret\_cast<ArkUI\_NodeHandle>(OH\_ArkUI\_NodeEvent\_GetUserData(event));
            if (textNode) {
                ArkUI\_NativeNodeAPI\_1 \*nodeApi = reinterpret\_cast<ArkUI\_NativeNodeAPI\_1 \*>(
                    OH\_ArkUI\_QueryModuleInterfaceByName(ARKUI\_NATIVE\_NODE, "ArkUI\_NativeNodeAPI\_1"));
                nodeApi->setAttribute(textNode, NODE\_TEXT\_CONTENT, &content);
            }
        });
    }
    

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/29/v3/y2yXdyz4SQiW-u8_MfwRdw/zh-cn_image_0000002633848792.gif?HW-CC-KV=V1&HW-CC-Date=20260709T132314Z&HW-CC-Expire=86400&HW-CC-Sign=A787F2133B1FE8FCC9FFE4186789DDCFB8990A3BCBD7CC55363E2431C57687C1)