鸿蒙开发入门day19-使用NDK接口构建UI(二)

news2024/9/20 15:12:51

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,还请三连支持一波哇ヾ(@^∇^@)ノ)

目录

监听组件事件

绑定手势事件

单一手势

组合手势

顺序识别

互斥识别

自定义手势判定


监听组件事件

NDK接口针对UI组件的事件,提供了监听函数的方式。首先,可使用addNodeEventReceiver函数添加组件事件的监听器,该监听器会监听该组件上发生的所有事件,例如:点击事件、焦点事件。然后,可使用registerNodeEvent函数声明组件的哪些事件需要监听,NDK接口支持的事件范围通过ArkUI_NodeEventType枚举值定义。

说明

  • 事件注册需要声明addNodeEventReceiver监听器注册和registerNodeEvent事件类型,监听器只能监听已声明的事件。

  • 需要关注事件的反注册逻辑,如在组件销毁前调用removeNodeEventReceiver移除事件监听器,unregisterNodeEvent通知ArkUI框架已监听的事件不再需要监听。

  • addNodeEventReceiver可以添加多个函数指针,每个函数指针都会在对应事件触发时触发,对应的removeNodeEventReceiver需要传递对应的函数指针用于移除监听。

  • registerNodeEventReceiver是全局监听函数,不同于addNodeEventReceiver,registerEventReceiver能够监听所有Native组件的事件触发,但只能传递一个函数指针,多次调用使用最后一次的函数指针进行回调,释放时使用ungisterNodeEventReceiver进行释放。

以下示例基于接入ArkTS页面章节,补充相关事件监听。

1.在ArkUINode基类对象中实现通用事件注册逻辑。

// ArkUINode.h
// 提供通用属性和事件的封装。

#ifndef MYAPPLICATION_ARKUINODE_H
#define MYAPPLICATION_ARKUINODE_H

#include "ArkUIBaseNode.h"
#include "NativeModule.h"

#include <arkui/native_node.h>
#include <arkui/native_type.h>

namespace NativeModule {

class ArkUINode : public ArkUIBaseNode {
public:
    explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {
        nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
        // 事件触发时需要通过函数获取对应的事件对象,这边通过设置节点自定义数据将封装类指针保持在组件上,方便后续事件分发。
        nativeModule_->setUserData(handle_, this);
        // 注册节点监听事件接受器。
        nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
    }

    ~ArkUINode() override {
        if (onClick_) {
            nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK);
        }
        if (onTouch_) {
            nativeModule_->unregisterNodeEvent(handle_, NODE_TOUCH_EVENT);
        }
        if (onDisappear) {
            nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR);
        }
        if (onAppear) {
            nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_APPEAR);
        }
        nativeModule_->removeNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
    }

    void SetWidth(float width) {
        assert(handle_);
        ArkUI_NumberValue value[] = {{.f32 = width}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
    }
    void SetPercentWidth(float percent) {
        assert(handle_);
        ArkUI_NumberValue value[] = {{.f32 = percent}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
    }
    void SetHeight(float height) {
        assert(handle_);
        ArkUI_NumberValue value[] = {{.f32 = height}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
    }
    void SetPercentHeight(float percent) {
        assert(handle_);
        ArkUI_NumberValue value[] = {{.f32 = percent}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
    }
    void SetBackgroundColor(uint32_t color) {
        assert(handle_);
        ArkUI_NumberValue value[] = {{.u32 = color}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
    }
    // 处理通用事件。
    void RegisterOnClick(const std::function<void()> &onClick) {
        assert(handle_);
        onClick_ = onClick;
        // 注册点击事件。
        nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK, 0, nullptr);
    }

    void RegisterOnTouch(const std::function<void(int32_t type, float x, float y)> &onTouch) {
        assert(handle_);
        onTouch_ = onTouch;
        // 注册触碰事件。
        nativeModule_->registerNodeEvent(handle_, NODE_TOUCH_EVENT, 0, nullptr);
    }

    void RegisterOnDisappear(const std::function<void()> &onDisappear) {
        assert(handle_);
        onDisappear_ = onDisappear;
        // 注册卸载事件。
        nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr);
    }

    void RegisterOnAppear(const std::function<void()> &onAppear) {
        assert(handle_);
        onAppear_ = onAppear;
        // 注册挂载事件。
        nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr);
    }

protected:
    // 事件监听器函数指针。
    static void NodeEventReceiver(ArkUI_NodeEvent *event) {
        // 获取事件发生的UI组件对象。
        auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event);
        // 获取保持在UI组件对象中的自定义数据,返回封装类指针。
        auto *node = reinterpret_cast<ArkUINode *>(
            NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
        // 基于封装类实例对象处理事件。
        node->ProcessNodeEvent(event);
    }
    void ProcessNodeEvent(ArkUI_NodeEvent *event) {
        auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
        switch (eventType) {
        case NODE_ON_CLICK: {
            if (onClick_) {
                onClick_();
            }
            break;
        }
        case NODE_TOUCH_EVENT: {
            if (onTouch_) {
                auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
                float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
                float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
                auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent);
                onTouch_(type, x, y);
            }
        }
        case NODE_EVENT_ON_DISAPPEAR: {
            if (onDisappear_) {
                onDisappear_();
            }
            break;
        }
        case NODE_EVENT_ON_APPEAR: {
            if (onAppear_) {
                onAppear_();
            }
            break;
        }
        default: {
            // 组件特有事件交给子类处理
            OnNodeEvent(event);
        }
        }
    }

    virtual void OnNodeEvent(ArkUI_NodeEvent *event) {}

    void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
        nativeModule_->addChild(handle_, child->GetHandle());
    }

    void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
        nativeModule_->removeChild(handle_, child->GetHandle());
    }

    void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
        nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
    }

private:
    std::function<void()> onClick_;
    std::function<void()> onDisappear_;
    std::function<void()> onAppear_;
    std::function<void(int32_t type, float x, float y)> onTouch_;
};
} // namespace NativeModule

#endif // MYAPPLICATION_ARKUINODE_H

2.在ArkUIListNode对象中实现列表事件注册逻辑。

// ArkUIListNode.h
// 列表封装类对象

#ifndef MYAPPLICATION_ARKUILISTNODE_H
#define MYAPPLICATION_ARKUILISTNODE_H

#include "ArkUINode.h"
#include <hilog/log.h>

namespace NativeModule {
class ArkUIListNode : public ArkUINode {
public:
    ArkUIListNode()
        : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {}

    ~ArkUIListNode() override { nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX); }

    void SetScrollBarState(bool isShow) {
        assert(handle_);
        ArkUI_ScrollBarDisplayMode displayMode =
            isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
        ArkUI_NumberValue value[] = {{.i32 = displayMode}};
        ArkUI_AttributeItem item = {value, 1};
        nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
    }

    // 注册列表相关事件。
    void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) {
        assert(handle_);
        onScrollIndex_ = onScrollIndex;
        nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr);
    }

protected:
   // 处理List相关事件。
    void OnNodeEvent(ArkUI_NodeEvent *event) override {
        auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
        switch (eventType) {
        case NODE_LIST_ON_SCROLL_INDEX: {
            auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0];
            if (onScrollIndex_) {
                onScrollIndex_(index.i32);
            }
        }
        default: {
        }
        }
    }

private:
    std::function<void(int32_t index)> onScrollIndex_;
};
} // namespace NativeModule

#endif // MYAPPLICATION_ARKUILISTNODE_H

3.添加相关事件。

// TextListExample.h
// 文本列表示例。

#ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
#define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H

#include "ArkUIBaseNode.h"
#include "ArkUIListItemNode.h"
#include "ArkUIListNode.h"
#include "ArkUITextNode.h"
#include <hilog/log.h>

namespace NativeModule {

std::shared_ptr<ArkUIBaseNode> CreateTextListExample() {
    // 创建组件并挂载
    // 1:创建List组件。
    auto list = std::make_shared<ArkUIListNode>();
    list->SetPercentWidth(1);
    list->SetPercentHeight(1);
    // 2:创建ListItem子组件并挂载到List上。
    for (int32_t i = 0; i < 30; ++i) {
        auto listItem = std::make_shared<ArkUIListItemNode>();
        auto textNode = std::make_shared<ArkUITextNode>();
        textNode->SetTextContent(std::to_string(i));
        textNode->SetFontSize(16);
        textNode->SetPercentWidth(1);
        textNode->SetHeight(100);
        textNode->SetBackgroundColor(0xFFfffacd);
        textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
        listItem->AddChild(textNode);
        // 列表项注册点击事件。
        listItem->RegisterOnClick([i]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", i); });
        list->AddChild(listItem);
    }
    // 3:注册List相关监听事件.
    list->RegisterOnScrollIndex([](int32_t index) { OH_LOG_INFO(LOG_APP, "on list scroll index: %{public}d", index); });
    // 4: 注册挂载事件。
    list->RegisterOnAppear([]() { OH_LOG_INFO(LOG_APP, "on list mount to tree"); });
    // 4: 注册卸载事件。
    list->RegisterOnDisappear([]() { OH_LOG_INFO(LOG_APP, "on list unmount from tree"); });
    return list;
}
} // namespace NativeModule

#endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H

绑定手势事件

ArkUI开发框架在NDK接口主要提供点击手势、拖动手势、滑动手势、长按手势、捏合手势和旋转手势,通过给指定的组件绑定不同的手势并设置相应的回调,实现期望的手势交互能力。

下面通过一个简单的示例来介绍如何实现手势绑定。

1.创建一个Column节点,用于绑定手势。

// 创建Column节点
auto column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
// 设置背景色
ArkUI_NumberValue value[] = {{.u32 = 0xff112233}};
ArkUI_AttributeItem item = {value, 1};
nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &item);
// 设置宽度
ArkUI_NumberValue widthValue[] = {{400}};
ArkUI_AttributeItem width = {widthValue, 1};
nodeAPI->setAttribute(column, NODE_WIDTH, &width);
// 设置高度
ArkUI_NumberValue heightValue[] = {{400}};
ArkUI_AttributeItem height = {heightValue, 1};
nodeAPI->setAttribute(column, NODE_HEIGHT, &height);

2.创建一个单指长按1秒并持续响应的长按手势。

// 获取手势Native接口集合
auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
            OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
// 创建长按手势
auto longPressGesture = gestureApi->createLongPressGesture(1, true, 1000);

3.将创建的手势和步骤一中创建的Column节点绑定。

// 设置回调
auto onActionCallBack = [](ArkUI_GestureEvent *event, void *extraParam) {
    // 回调内容
};

// 将手势设置到组件上
gestureApi->setGestureEventTarget(longPressGesture, GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE | GESTURE_EVENT_ACTION_END, column, onActionCallBack);

gestureApi->addGestureToNode(column, longPressGesture, PARALLEL, NORMAL_GESTURE_MASK);

单一手势

通过上文的示例已经了解了如果将手势绑定在节点上,接下来将分别介绍不同手势的创建方法,并分别支持哪些事件回调。

点击手势

通过给组件绑定点击手势可在组件被点击时触发此回调,可指定触发回调需要的点击次数和手指个数。

ArkUI_GestureRecognizer* (*createTapGesture)(int32_t countNum, int32_t fingersNum);

拖动手势

通过给组件绑定拖动手势可在用户拖动组件时触发回调,可指定触发回调需要的手指个数、拖动方向、拖动距离。单位为px。

ArkUI_GestureRecognizer* (*createPanGesture)(
int32_t fingersNum, ArkUI_GestureDirectionMask directions, double distanceNum);

长按手势

通过给组件绑定长按手势可在用户长按组件时触发回调,可指定触发回调需要的手指个数、长按时间(单位毫秒)、是否连续触发。

ArkUI_GestureRecognizer* (*createLongPressGesture)(int32_t fingersNum, bool repeatResult, int32_t durationNum);

捏合手势

通过给组件绑定捏合手势可在用户捏合组件时触发回调,可指定触发回调需要的手指个数(最小为2)、捏合距离(单位px)。

ArkUI_GestureRecognizer* (*createPinchGesture)(int32_t fingersNum, double distanceNum);

组合手势

组合手势由多种单一手势组合而成,通过在GroupGesture中使用不同的ArkUI_GroupGestureMode来声明该组合手势的类型,支持顺序识别、并行识别、互斥识别三种类型。

ArkUI_GroupGestureMode枚举类,用于声明该组合手势的类型。顺序识别SEQUENTIAL_GROUP,并行识别PARALLEL_GROUP,互斥识别EXCLUSIVE_GROUP。

顺序识别

顺序识别组合手势对应的ArkUI_GroupGestureMode为SEQUENTIAL_GROUP。顺序识别组合手势将按照手势的注册顺序识别手势,直到所有的手势识别成功。当顺序识别组合手势中有一个手势识别失败时,后续手势识别均失败。顺序识别手势组仅有最后一个手势可以响应GESTURE_EVENT_ACTION_END。

以顺序识别长按和滑动手势为例:

ArkUI_NodeHandle testGestureExample() {
    auto column = nodeAPI->createNode(ARKUI_NODE_COLUMN);

    // 创建手势并设置回调
    ArkUI_NumberValue value[] = {{.u32 = 0xff112233}};
    ArkUI_AttributeItem item = {value, 1};
    nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &item);
    ArkUI_NumberValue widthValue[] = {{200}};
    ArkUI_AttributeItem width = {widthValue, 1};
    nodeAPI->setAttribute(column, NODE_WIDTH, &width);
    ArkUI_NumberValue heightValue[] = {{200}};
    ArkUI_AttributeItem height = {heightValue, 1};
    nodeAPI->setAttribute(column, NODE_HEIGHT, &height);

    // 判断是否有手势API
    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
        OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
    if (gestureApi->createGroupGesture) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, createGroupGesture api exist");
    } else {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, createGroupGesture api not exist");
    }
    auto groupGesture = gestureApi->createGroupGesture(ArkUI_GroupGestureMode::SEQUENTIAL_GROUP);

    // 创建长按手势
    auto longPressGesture = gestureApi->createLongPressGesture(1, true, 500);
    if (gestureApi->getGestureType) {
        ArkUI_GestureRecognizerType type = gestureApi->getGestureType(longPressGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack longPressGesture,ArkUI_GestureRecognizerType%{public}d", type);
    }
    // 给长按手势定回调
    auto onActionCallBackPanLongPress = [](ArkUI_GestureEvent *event, void *extraParam) {
        ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);

        float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
        float velocityX = OH_ArkUI_PanGesture_GetVelocityX(event);
        float velocityY = OH_ArkUI_PanGesture_GetVelocityY(event);
       float OffsetX = OH_ArkUI_PanGesture_GetOffsetX(event);
        float OffsetY = OH_ArkUI_PanGesture_GetOffsetY(event);
        float scale = OH_ArkUI_PinchGesture_GetScale(event);
        float CenterX = OH_ArkUI_PinchGesture_GetCenterX(event);
        float CenterY = OH_ArkUI_PinchGesture_GetCenterY(event);
        float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
        float VelocityS = OH_ArkUI_SwipeGesture_GetVelocity(event);
        float angleR = OH_ArkUI_RotationGesture_GetAngle(event);
       float repeat = OH_ArkUI_LongPress_GetRepeatCount(event);

        OH_LOG_Print(
            LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
            "onPanActionCallBack,longPressGesturecallback actionType:%{public}d,velocity%{public}f,velocityX"
            "%{public}f;"
            "velocityY%{public}f,OffsetX%{public}f,OffsetY%{public}f,scale%{public}fCenterX"
            "%{public}fCenterY"
            "%{public}fangle%{public}fVelocityS%{public}fangleR%{public}frepeat%{public}f",
            actionType, velocity, velocityX, velocityY, OffsetX, OffsetY, scale, CenterX, CenterY, angle, VelocityS,
            angleR, repeat);
    };
    gestureApi->setGestureEventTarget(longPressGesture,
                                      GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE | GESTURE_EVENT_ACTION_CANCEL,
                                      column, onActionCallBackPanLongPress);

    // 将长按手势添加到手势组
    if (gestureApi->addChildGesture) {
        gestureApi->addChildGesture(groupGesture, longPressGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "onPanActionCallBack, addChildGesture longPressGesture");
    }
    // 创建滑动手势 swipe
    auto swipeGesture = gestureApi->createSwipeGesture(1, GESTURE_DIRECTION_ALL, 100);
    if (gestureApi->getGestureType) {
        ArkUI_GestureRecognizerType type = gestureApi->getGestureType(swipeGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, ArkUI_GestureRecognizerType %{public}d", type);
    }
    // 给滑动手势绑定回调
    auto onActionCallBack = [](ArkUI_GestureEvent *event, void *extraParam) {
        ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);

        float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
        float velocityX = OH_ArkUI_PanGesture_GetVelocityX(event);
        float velocityY = OH_ArkUI_PanGesture_GetVelocityY(event);
        float OffsetX = OH_ArkUI_PanGesture_GetOffsetX(event);
        float OffsetY = OH_ArkUI_PanGesture_GetOffsetY(event);
        float scale = OH_ArkUI_PinchGesture_GetScale(event);
        float CenterX = OH_ArkUI_PinchGesture_GetCenterX(event);
        float CenterY = OH_ArkUI_PinchGesture_GetCenterY(event);
        float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
        float VelocityS = OH_ArkUI_SwipeGesture_GetVelocity(event);
        float angleR = OH_ArkUI_RotationGesture_GetAngle(event);
        float repeat = OH_ArkUI_LongPress_GetRepeatCount(event);



        // 通过日志查看
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, swipeGesture callback actionType: %{public}d, velocity "
                     "%{public}f,velocityX "
                     "%{public}f; "
                     "velocityY %{public}f, OffsetX %{public}f, OffsetY %{public}f, scale %{public}fCenterX "
                     "%{public}f CenterY"
                     " %{public}f angle %{public}f VelocityS %{public}f angleR %{public}f repeat %{public}f",
                     actionType, velocity, velocityX, velocityY, OffsetX, OffsetY, scale, CenterX, CenterY, angle,
                     VelocityS, angleR, repeat);

        ArkUI_NumberValue value[] = {{.f32 = 0}, {.f32 = 0}, {.f32 = 0}, {.f32 = angleR}, {.f32 = 0}};
        ArkUI_AttributeItem item = {value, 5};
        auto column = reinterpret_cast<ArkUI_NodeHandle>(extraParam);
        nodeAPI->setAttribute(column, NODE_ROTATE, &item);
    };

    gestureApi->setGestureEventTarget(
        swipeGesture, GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE | GESTURE_EVENT_ACTION_END, column,
        onActionCallBack);

    // 将滑动手势添加到手势组
    if (gestureApi->addChildGesture) {
        gestureApi->addChildGesture(groupGesture, swipeGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, addChildGesture swipeGesture");
    }
    // 将手势组设置到组件上
    gestureApi->addGestureToNode(column, groupGesture, PRIORITY, NORMAL_GESTURE_MASK);
    return column;
}

互斥识别

互斥识别组合手势对应的ArkUI_GroupGestureMode为EXCLUSIVE_GROUP。互斥识别组合手势中注册的手势将同时进行识别,若有一个手势识别成功,则结束手势识别,其他所有手势识别失败。

以互斥识别平移手势和捏合手势为例:

ArkUI_NodeHandle testGestureExample() {
    auto column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    auto button = nodeAPI->createNode(ARKUI_NODE_BUTTON);

    // 创建手势并设置回调
    ArkUI_NumberValue value[] = {{.u32 = 0xff112233}};
    ArkUI_AttributeItem item = {value, 1};
    nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &item);
    ArkUI_NumberValue widthValue[] = {{200}};
    ArkUI_AttributeItem width = {widthValue, 1};
    nodeAPI->setAttribute(column, NODE_WIDTH, &width);
    ArkUI_NumberValue heightValue[] = {{200}};
    ArkUI_AttributeItem height = {heightValue, 1};
    nodeAPI->setAttribute(column, NODE_HEIGHT, &height);

    // 判断是否有手势API
    auto gestureApi = reinterpret_cast<ArkUI_NativeGestureAPI_1 *>(
        OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_GESTURE, "ArkUI_NativeGestureAPI_1"));
    if (gestureApi->createGroupGesture) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, createGroupGesture api exist");
    } else {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack, createGroupGesture api not exist");
    }
    auto groupGesture = gestureApi->createGroupGesture(ArkUI_GroupGestureMode::EXCLUSIVE_GROUP);

    // 创建拖动手势
    auto panGesture = gestureApi->createPanGesture(1, GESTURE_DIRECTION_VERTICAL, 5);
    if (gestureApi->getGestureType) {
        ArkUI_GestureRecognizerType type = gestureApi->getGestureType(panGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack panGesture, ArkUI_GestureRecognizerType %{public}d", type);
    }
    // 给拖动手势绑定回调
    auto onActionCallBackPan = [](ArkUI_GestureEvent *event, void *extraParam) {
        ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);

        float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
        float velocityX = OH_ArkUI_PanGesture_GetVelocityX(event);
        float velocityY = OH_ArkUI_PanGesture_GetVelocityY(event);
        float OffsetX = OH_ArkUI_PanGesture_GetOffsetX(event);
        float OffsetY = OH_ArkUI_PanGesture_GetOffsetY(event);
        float scale = OH_ArkUI_PinchGesture_GetScale(event);
        float CenterX = OH_ArkUI_PinchGesture_GetCenterX(event);
        float CenterY = OH_ArkUI_PinchGesture_GetCenterY(event);
        float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
        float VelocityS = OH_ArkUI_SwipeGesture_GetVelocity(event);
        float angleR = OH_ArkUI_RotationGesture_GetAngle(event);
        float repeat = OH_ArkUI_LongPress_GetRepeatCount(event);

        // 通过日志查看
        OH_LOG_Print(
            LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
            "onPanActionCallBack, panGesture callback actionType: %{public}d, velocity %{public}f,velocityX "
            "%{public}f; "
            "velocityY %{public}f, OffsetX %{public}f, OffsetY %{public}f, scale %{public}fCenterX "
            "%{public}f CenterY"
            " %{public}f angle %{public}f VelocityS %{public}f angleR %{public}f repeat %{public}f",
            actionType, velocity, velocityX, velocityY, OffsetX, OffsetY, scale, CenterX, CenterY, angle, VelocityS,
            angleR, repeat);
    };
    gestureApi->setGestureEventTarget(panGesture,
                                      GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
                                          GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
                                      column, onActionCallBackPan);
    // 将拖动手势添加到手势组
    if (gestureApi->addChildGesture) {
        gestureApi->addChildGesture(groupGesture, panGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "onPanActionCallBack, addChildGesture panGesture");
    }
    // 创建捏合手势
    auto pinchGesture = gestureApi->createPinchGesture(0, 0);
    if (gestureApi->getGestureType) {
        ArkUI_GestureRecognizerType type = gestureApi->getGestureType(pinchGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "onPanActionCallBack pinchGesture, ArkUI_GestureRecognizerType %{public}d", type);
    }
    // 给捏合手势绑定回调
    auto onActionCallBack = [](ArkUI_GestureEvent *event, void *extraParam) {
        ArkUI_GestureEventActionType actionType = OH_ArkUI_GestureEvent_GetActionType(event);

        float velocity = OH_ArkUI_PanGesture_GetVelocity(event);
        float velocityX = OH_ArkUI_PanGesture_GetVelocityX(event);
        float velocityY = OH_ArkUI_PanGesture_GetVelocityY(event);
        float OffsetX = OH_ArkUI_PanGesture_GetOffsetX(event);
        float OffsetY = OH_ArkUI_PanGesture_GetOffsetY(event);
        float scale = OH_ArkUI_PinchGesture_GetScale(event);
        float CenterX = OH_ArkUI_PinchGesture_GetCenterX(event);
        float CenterY = OH_ArkUI_PinchGesture_GetCenterY(event);
        float angle = OH_ArkUI_SwipeGesture_GetAngle(event);
        float VelocityS = OH_ArkUI_SwipeGesture_GetVelocity(event);
        float angleR = OH_ArkUI_RotationGesture_GetAngle(event);
        float repeat = OH_ArkUI_LongPress_GetRepeatCount(event);



        OH_LOG_Print(
            LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
            "onPanActionCallBack, pinchGesture callback actionType: %{public}d, velocity %{public}f,velocityX "
            "%{public}f; "
            "velocityY %{public}f, OffsetX %{public}f, OffsetY %{public}f, scale %{public}fCenterX "
            "%{public}f CenterY"
            " %{public}f angle %{public}f VelocityS %{public}f angleR %{public}f repeat %{public}f",
            actionType, velocity, velocityX, velocityY, OffsetX, OffsetY, scale, CenterX, CenterY, angle, VelocityS,
            angleR, repeat);



        ArkUI_NumberValue value[] = {{.f32 = scale}, {.f32 = scale}};
        ArkUI_AttributeItem item = {value, 2};
        auto column = reinterpret_cast<ArkUI_NodeHandle>(extraParam);
        nodeAPI->setAttribute(column, NODE_SCALE, &item);
    };
    gestureApi->setGestureEventTarget(pinchGesture,
                                      GESTURE_EVENT_ACTION_ACCEPT | GESTURE_EVENT_ACTION_UPDATE |
                                          GESTURE_EVENT_ACTION_END | GESTURE_EVENT_ACTION_CANCEL,
                                      column, onActionCallBack);
    // 将捏合手势添加到手势组
    if (gestureApi->addChildGesture) {
        gestureApi->addChildGesture(groupGesture, pinchGesture);
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "onPanActionCallBack, addChildGesture pinchGesture");
    }
    // 将手势组设置到组件上
    gestureApi->addGestureToNode(column, groupGesture, PRIORITY, NORMAL_GESTURE_MASK);
    return column;
}

自定义手势判定

支持自定义手势判定,当组件触发手势时,可根据回调内容判定当前响应的手势是否继续执行。

在上文绑定手势事件的示例中按照如下方式进行调整即可实现自定义手势判定。

1.创建自定义手势判定回调。

    auto onInterruptCallback = [](ArkUI_GestureInterruptInfo *info) -> ArkUI_GestureInterruptResult {
        // 获取是否系统手势
        auto systag = OH_ArkUI_GestureInterruptInfo_GetSystemFlag(info);
        // 获取拦截的手势指针
        auto recognizer = OH_ArkUI_GestureInterruptInfo_GetRecognizer(info);
        // 获取系统手势类型
        auto systemRecognizerType = OH_ArkUI_GestureInterruptInfo_GetSystemRecognizerType(info);
        // 获取手势事件
        auto gestureEvent = OH_ArkUI_GestureInterruptInfo_GetGestureEvent(info);
        auto inputevent = OH_ArkUI_GestureEvent_GetRawInputEvent(gestureEvent);

        if (systag) {
            // 如果是系统手势则不拦截
            return GESTURE_INTERRUPT_RESULT_CONTINUE;
        } else {
            // 不是系统手势则拒绝
            return GESTURE_INTERRUPT_RESULT_REJECT;
        }
    };

2.绑定手势判定和节点。

gestureApi->setGestureInterrupterToNode(column, onInterruptCallback);

【IEEE出版丨EI检索】第三届云计算、大数据应用与软件工程国际学术会议 (CBASE 2024)_艾思科蓝_学术一站式服务平台 

更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2142085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

异常知识总结

就是报错&#xff0c;就是不处理一下&#xff0c;程序运行到这里就直接终止了&#xff0c;输出报错信息。 但是我们用异常处理&#xff0c;能让他程序不停止不报错。 比如正常1/0程序肯定报错&#xff0c;用异常处理就不报错了。 ![在这里插入图片描述](https://i-blog.csdnim…

C++笔记---二叉搜索树

1. 二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: • 若它的左子树不为空&#xff0c;则左子树上所有结点的值都小于等于根结点的值。 • 若它的右子树不为空&#xff0c;则右子树上所有结点的值都大于等于…

【CTF Reverse】XCTF GFSJ1092 easyEZbaby_app Writeup(Android+逆向工程+Java)

easyEZbaby_app 究极简单的安卓逆向 解法 得到一个 apk 安装包。 用 jadx 打开&#xff0c;搜索文本 flag&#xff0c;加载所有。 flag 是 obj obj2&#xff0c;来自用户的用户名和密码。 Override // android.view.View.OnClickListenerpublic void onClick(View view) {St…

看Threejs好玩示例,学习创新与技术(ProjectTexture合集)

本文是一个合集,稍微对ProjectTexture的技术进行总结,突出关键和创意。 演示视频如下(Playing with Texture Projection in Three.js | Codrops (tympanus.net)): 20240909_232959 1、它的创新与用途? 这个案例中模型方块游荡的方式像水波,鼠标放上面如棍子放在水里一样…

基于python+django+vue的旅游网站系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤pythondjangovue…

网络(四)——HTTP协议

文章目录 认识urlurlencode和urldecodeHTTP协议格式HTTP的方法HTTP的状态码HTTP常见Header 虽然应用层的协议是由人为规定的&#xff0c;但是已经有大佬们定义了一些现成的&#xff0c;又非常好用的应用层协议&#xff0c;供我们直接参考使用. HTTP(超文本传输协议)就是其中之一…

【PCB工艺】如何实现PCB板层间的互连

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言①、什么是通孔②、通孔是怎样产生的③、通孔种类④、盘中孔⑤、设计建议 前言 送给大学毕业后找不到奋斗方向的你…

AWS 将 OpenSearch 纳入 Linux 基金会旗下

AWS 今天宣布&#xff0c;随着OpenSearch 基金会的成立&#xff0c;它将把OpenSearch&#xff08;流行的 Elasticsearch 搜索和分析引擎的开源分叉&#xff09;移交给 Linux 基金会。在 Elastic 将其 Elasticsearch 和 Kibana 项目的许可证更改为自己的专有许可证 Elastic Lice…

力扣题解1184

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述&#xff08;简单&#xff09;&#xff1a; 公交站间的距离 环形公交路线上有 n 个站&#xff0c;按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离&#xff0c;distanc…

Vue3+Element Plus:使用el-dialog,对话框可拖动,且对话框弹出时仍然能够在背景页(对话框外部的页面部分)上进行滚动以及输入框输入信息

【需求】 使用Element Plus中的el-dialog默认是模态的&#xff08;即它会阻止用户与对话框外部的元素进行交互&#xff09;&#xff0c;对话框弹出时仍然能够在背景页&#xff08;对话框外部的页面部分&#xff09;上进行滚动以及输入框输入信息&#xff0c;且对话框可拖动 【…

卷积——入门理解

一、卷积的通俗理解 卷积的意义——通俗易懂的理解&#xff08;以吃馒头为例&#xff09; 二、 卷积的深入理解 1、卷积能解决什么问题 可以用来计算拥有记忆系统的输出问题 无记忆&#xff1a;当前的输出仅取决于当前的输入&#xff0c;而与之前的输入无关 例如&#xff1…

SpringMVC1~~~

快速入门 spring容器文件 在src下就是applicationContext-mvc.xml&#xff0c;需要在web.xml指定<init-param>&#xff0c;给DispatcherServlet指定要去操作的spring容器文件 在WEB-INF下就是xxx-servlet.xml&#xff0c;不需要在web.xml指定<init-param>,如果我们…

Zookeeper工作机制和特点

1. Zookeeper工作机制 Zookeeper从设计模式角度来理解&#xff1a; 是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它负责存储和管理大家都关心的数据&#xff0c;然后接受观察者的 注册&#xff0c;一旦这些数据的状态发生变化&#xff0c;Zookeeper就将负责通知…

xml重点笔记(尚学堂 3h)

XML:可扩展标记语言 主要内容(了解即可) 1.XML介绍 2.DTD 3.XSD 4.DOM解析 6.SAX解析 学习目标 一. XML介绍 1.简介 XML(Extensible Markup Language) 可扩展标记语言&#xff0c;严格区分大小写 2.XML和HTML XML是用来传输和存储数据的。 XML多用在框架的配置文件…

基于Python DoIPClient库的DoIP上位机开发手顺

代码 address, announcement DoIPClient.await_vehicle_announcement()logical_address announcement.logical_addressip, port addressprint(ip, port, logical_address) 效果 代码 address, announcement DoIPClient.get_entity(ecu_ip_addresssIp, protocol_version3…

【VitualBox】VitualBox的网络模式+网络配置

VirtualBox 1. 简介 VirtualBox 是一款开源虚拟机软件&#xff0c;使用者可以在VirtualBox上安装并且执行Solaris、Windows、DOS、Linux、OS/2 Warp、BSD等系统作为客户端操作系统。 2. 六种网络接入模式 VirtualBox提供了多种网络接入模式&#xff0c;他们各有优缺点&#xf…

Setting Design Properties

设置设计属性 接下来&#xff0c;在设计上设置配置模式。这是导致物理 约束&#xff0c;在这种情况下是设计的属性&#xff0c;而不是单元的属性。首先&#xff0c;列出所有 当前设计的特性。 1.在Tcl控制台中列出设计的属性&#xff1a; list_property [current_design] 此命…

本地安装MySQL并配置环境变量

MySQL是一个关系型数据库管理系统&#xff0c;是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#xff0c;关系数据库管理系统) 应用软件之一。 本地安装MySQL 提供了 MySQ…

mysql笔记8(多表查询)

文章目录 1. union联合查询可能会用到去重操作 2. inner join 内连接3. left join 左连接4. right join 右连接5. cross join 交叉连接6. natural join 自然连接natural left join 自然左连接natural right join 自然右连接自然连接的两张表没有同名字段怎么办&#xff1f; 7. …

LLMs之SWIFT:SWIFT的简介、安装和使用方法、案例应用之详细攻略

LLMs之SWIFT&#xff1a;SWIFT的简介、安装和使用方法、案例应用之详细攻略 目录 SWIFT的简介 新闻 &#x1f6e0;️ 安装 &#x1f680; 快速开始 Web-UI 训练 训练脚本 支持的训练过程 单卡训练 模型并行训练 数据并行训练 Deepspeed训练 多机多卡 阿里云-DLC多…