目录

通过自绘制接入无障碍

通过自定义绘制接入的第三方框架平台,NDK提供了对接无障碍服务的接口函数,使三方框架组件能够支持ArkUI中的基本无障碍功能,包括焦点获取、获取无障碍节点和操作响应。

从API version 13开始,支持基于XComponent的自绘制方式接入。

从API version 23开始,支持基于CustomNode构建渲染节点树的自绘制方式接入。

三方框架从绘制容器组件获取到ArkUI_AccessibilityProvider,通过实现其中对接无障碍的回调函数,来适配无障碍系统发出的操作Action,并针对组件交互行为发送无障碍事件Event到无障碍子系统,实现无障碍辅助应用的交互体验。

基于XComponent的自绘制接入方式通过OH_NativeXComponent_GetNativeAccessibilityProvider获得无障碍接入ArkUI_AccessibilityProvider。

基于CustomNode构建渲染节点树的自绘制接入方式通过OH_ArkUI_NativeModule_GetNativeAccessibilityProvider获得无障碍接入ArkUI_AccessibilityProvider。

如果需要支持单实例,通过OH_ArkUI_AccessibilityProviderRegisterCallback注册接入无障碍所需的回调函数ArkUI_AccessibilityProviderCallbacks。

如果需要支持多实例,则通过OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance注册接入无障碍所需的回调函数ArkUI_AccessibilityProviderCallbacksWithInstance。

基于XComponent的自绘制接入方式

以下示例提供了对接无障碍能力的实现方法,仅包含主要步骤,完整示例请参考AccessibilityCapiSample。对接完成后,在开启无障碍功能时,可使XComponent中的三方框架绘制组件接入,实现无障碍交互。

  1. 按照自定义渲染(XComponent)的使用OH_ArkUI_SurfaceHolder管理Surface生命周期场景创建前置工程。

  2. 获得无障碍接入Provider并注册回调函数(以多实例场景为例)。

    #include <arkui/native_interface_accessibility.h>
    #include <string>
    #include "common/common.h"
    // 完整实现请参考AccessibilityCapiSample。
    #include "fakenode/fake_node.h"
    // 完整实现请参考AccessibilityCapiSample。
    #include "AccessibilityManager.h"
    
    // ...
    AccessibilityManager::AccessibilityManager()
    {
    // 多实例场景
        accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById = FindAccessibilityNodeInfosById;
        accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText;
        accessibilityProviderCallbacksWithInstance_.findFocusedAccessibilityNode = FindFocusedAccessibilityNode;
        accessibilityProviderCallbacksWithInstance_.findNextFocusAccessibilityNode = FindNextFocusAccessibilityNode;
        accessibilityProviderCallbacksWithInstance_.executeAccessibilityAction = ExecuteAccessibilityAction;
        accessibilityProviderCallbacksWithInstance_.clearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode;
        accessibilityProviderCallbacksWithInstance_.getAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition;
    // 单实例场景
        accessibilityProviderCallbacks_.findAccessibilityNodeInfosById = FindAccessibilityNodeInfosById;
        accessibilityProviderCallbacks_.findAccessibilityNodeInfosByText = FindAccessibilityNodeInfosByText;
        accessibilityProviderCallbacks_.findFocusedAccessibilityNode = FindFocusedAccessibilityNode;
        accessibilityProviderCallbacks_.findNextFocusAccessibilityNode = FindNextFocusAccessibilityNode;
        accessibilityProviderCallbacks_.executeAccessibilityAction = ExecuteAccessibilityAction;
        accessibilityProviderCallbacks_.clearFocusedFocusAccessibilityNode = ClearFocusedFocusAccessibilityNode;
        accessibilityProviderCallbacks_.getAccessibilityNodeCursorPosition = GetAccessibilityNodeCursorPosition;
    }
    
    void AccessibilityManager::Initialize(const std::string &id, OH_NativeXComponent *nativeXComponent)
    {
        int32_t ret = OH_NativeXComponent_GetNativeAccessibilityProvider(nativeXComponent, &provider);
        if (provider == nullptr) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT, "get provider is null");
            return;
        }
        // 2.注册回调函数
        ret = OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance(id.c_str(), provider,
            &accessibilityProviderCallbacksWithInstance_);
        if (ret != 0) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, LOG_PRINT_TEXT,
                         "OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance failed");
            return;
        }
        g_provider = provider;
    }
    
    // ...
  3. 三方框架需要实现如下回调函数。

provider通过回调函数OH_ArkUI_AccessibilityProviderRegisterCallback或者OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance对接成功后,可开启无障碍功能。

基于CustomNode的自绘制接入方式

  • 基于CustomNode的自定义绘制容器组件,仅支持类型为ARKUI_NODE_CUSTOM且无其他子节点的ArkUI_Node。绘制容器组件的宽和高不能为0,避免被无障碍辅助应用忽略或错误处理子节点树。

以下示例提供了对接无障碍能力的实现方法,仅包含主要步骤,完整示例请参考AccessibilityCustomCapi。回调函数实现请参考基于XComponent的自绘制接入方式。完成回调函数实现后,开启无障碍功能,基于CustomNode构建渲染节点树的三方框架即可接入无障碍服务,实现控件树的无障碍交互与信息查询。

  1. 按照基于CustomNode构建渲染节点树场景创建前置工程。

  2. 获取无障碍接入Provider实例,将回调函数与Provider实例绑定并完成注册。

    int32_t AccessibilityMaker::GetAccessibilityProvider(ArkUI_NodeHandle* customNode, const char* id)
    {
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosById =
            FindAccessibilityNodeInfosById;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.findAccessibilityNodeInfosByText =
            FindAccessibilityNodeInfosByText;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.findFocusedAccessibilityNode =
            FindFocusedAccessibilityNode;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.findNextFocusAccessibilityNode =
            FindNextFocusAccessibilityNode;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.executeAccessibilityAction =
            ExecuteAccessibilityAction;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.clearFocusedFocusAccessibilityNode =
            ClearFocusedFocusAccessibilityNode;
        AccessibilityMaker::accessibilityProviderCallbacksWithInstance_.getAccessibilityNodeCursorPosition =
            GetAccessibilityNodeCursorPosition;
    
        // 获取 native 层提供的 accessibility provider,并为其注册回调
        OH_ArkUI_NativeModule_GetNativeAccessibilityProvider(customNode, &accessibilityProvider_);
        if (accessibilityProvider_ == nullptr) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AccessibilityMaker", "accessibilityProvider_ is null");
            return -1;
        }
    
        int32_t ret = OH_ArkUI_AccessibilityProviderRegisterCallbackWithInstance(id, accessibilityProvider_,
            &AccessibilityMaker::accessibilityProviderCallbacksWithInstance_);
        if (ret != 0) {
            return ret;
        }
        return 0;
    }
  3. 三方框架需要实现回调函数。请参考前文的基于XComponent的自绘制接入方式。