【Android】Hippy自定义界面组件之手势事件处理

文章介绍了在App开发中扩展HippySDK的UI组件,如创建MyView,涉及扩展HippyViewController,实现createViewImpl、Props设置和手势处理。通过重写onTouchEvent并使用NativeGestureDispatcher来处理JS端的手势事件,如ON_TOUCH_DOWN、ON_TOUCH_MOVE等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义界面组件

App 开发中有可能使用到大量的UI组件,除了 Hippy SDK 已包括其中常用的部分,如ViewTextImage 等,我们仍可能需要对 UI 组件进行扩展封装。


组件扩展

我们将以MyView为例,从头介绍如何扩展组件。

扩展组件包括:

  1. 扩展 HippyViewController
  2. 实现 createViewImpl方法
  3. 实现 Props 设置方法。
  4. 手势事件处理。
  5. 注册 HippyViewController

HippyViewController 是一个视图管理的基类(如果是ViewGroup的组件,基类为 HippyGroupController)。 在这个例子中我们需要创建一个 MyViewController 类,它继承 HippyViewController<MyView>MyView 是被管理的UI组件类型,它应该是一个 Android View 或者 ViewGroup@HippyController 注解用来定义导出给JS使用时的组件信息。

手势事件处理

Hippy手势处理,复用了 Android 系统手势处理机制。扩展组件时,需要在控件的 onTouchEvent 添加部分代码,JS才能正常收到 onTouchDownonTouchMoveonTouchEnd 事件。事件的详细介绍,参考 Hippy 事件机制。

@Override
public NativeGestureDispatcher getGestureDispatcher()
{
    return mGestureDispatcher;
}

@Override
public void setGestureDispatcher(NativeGestureDispatcher dispatcher)
{
    mGestureDispatcher = dispatcher;
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
    boolean result = super.onTouchEvent(event);
    if (mGestureDispatcher != null)
    {
        result |= mGestureDispatcher.handleTouchEvent(event);
    }
    return result;
}

源码

  1. 手势事件处理的入口
mGestureDispatcher.handleTouchEvent(event);

public boolean handleTouchEvent(MotionEvent event) {
  if (mGestureProcessor == null) {
    mGestureProcessor = new NativeGestureProcessor(this);
  }
  /* 分析1 */
  return mGestureProcessor.onTouchEvent(event);
}
  1. / 分析1 /NativeGestureProcessor 针对安卓的事件机制,对不同的事件做了不同的处理,有两个重要方法:
    • needHandle : 判断是否需要处理对应的事件
    • handle : 对事件进行相应的处理
public boolean onTouchEvent(MotionEvent event) {
  int action = event.getAction() & MotionEvent.ACTION_MASK;
  boolean handle = false;
  switch (action) {
    case MotionEvent.ACTION_DOWN: {
      if (mCallback.needHandle(NodeProps.ON_PRESS_IN)) {
        mNoPressIn = false;
        mLastPressInX = event.getX();
        mLastPressInY = event.getY();
        getGestureHandler().sendEmptyMessageDelayed(PRESS_IN, TAP_TIMEOUT);
        handle = true;
      } else {
        mNoPressIn = true;
      }

      if (/* 分析2 a */mCallback.needHandle(NodeProps.ON_TOUCH_DOWN)) {
        /* 分析2 b */mCallback.handle(NodeProps.ON_TOUCH_DOWN, event.getX(), event.getY());
        handle = true;
      }
      ...
    }
  return handle;
}
  1. /* 分析2 */NativeGestureDispatcherneedHandle & handle
/* 分析2 a */
// mGestureTypes 内包含则需要处理
public boolean needHandle(String type) {
  ...
  boolean result = mGestureTypes.contains(type);
  ...
  return result;
  ...
}

/* 分析2 b */
// 对几种不同的事件进行了默认处理, 我们以 handleTouchDown 为例
public void handle(String type, float x, float y) {
  if (mTargetView == null) {
    LogUtils.e("NativeGestureDispatcher", "handle!!! but view is null!!!!");
    return;
  }

  if (TextUtils.equals(type, NodeProps.ON_PRESS_IN)) {
    handlePressIn(mEngineContext, mTargetView.getId());
  } else if (TextUtils.equals(type, NodeProps.ON_PRESS_OUT)) {
    handlePressOut(mEngineContext, mTargetView.getId());
  } else if (TextUtils.equals(type, NodeProps.ON_TOUCH_DOWN)) {
    NativeGestureDispatcher
        .handleTouchDown(mEngineContext, mTargetView.getId(), x, y, mTargetView.getId());
  } else if (TextUtils.equals(type, NodeProps.ON_TOUCH_MOVE)) {
    NativeGestureDispatcher
        .handleTouchMove(mEngineContext, mTargetView.getId(), x, y, mTargetView.getId());
  } else if (TextUtils.equals(type, NodeProps.ON_TOUCH_END)) {
    NativeGestureDispatcher
        .handleTouchEnd(mEngineContext, mTargetView.getId(), x, y, mTargetView.getId());
  } else if (TextUtils.equals(type, NodeProps.ON_TOUCH_CANCEL)) {
    NativeGestureDispatcher
        .handleTouchCancel(mEngineContext, mTargetView.getId(), x, y, mTargetView.getId());
  }
}

// 将事件名称以及触点坐标发送给前端
public static void handleTouchDown(HippyEngineContext context, int mTagId, float x, float y,
    int viewId) {
  int[] viewCoords = new int[2];
  getLocationInWindow(context, viewId, viewCoords);
  HippyMap params = new HippyMap();
  params.pushString(KEY_EVENT_NAME, NodeProps.ON_TOUCH_DOWN);
  params.pushInt(KEY_TAG_ID, mTagId);
  params.pushDouble(KEY_PAGE_X, PixelUtil.px2dp(viewCoords[0] + x));
  params.pushDouble(KEY_PAGE_Y, PixelUtil.px2dp(viewCoords[1] + y));
  context.getModuleManager().getJavaScriptModule(EventDispatcher.class)
      .receiveNativeGesture(params);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄才不管那么多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值