自定义界面组件

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使用时的组件信息。

  1. @HippyController(name = "MyView")
  2. public class MyViewController extends HippyViewController<MyView>
  3. {
  4. ...
  5. }

实现 createViewImpl 方法

当需要创建对视图时,引擎会调用 createViewImpl 方法。

  1. @Override
  2. protected View createViewImpl(Context context)
  3. {
  4. // context实际类型为HippyInstanceContext
  5. return new MyView(context);
  6. }

实现属性 Props 方法

需要接收 JS 设置的属性,需要实现带有 @HippyControllerProps 注解的方法。

@HippyControllerProps 可用参数包括:

  • name(必须):导出给JS的属性名称。
  • defaultType(必须):默认的数据类型。取值包括 HippyControllerProps.BOOLEANHippyControllerProps.NUMBERHippyControllerProps.STRINGHippyControllerProps.DEFAULTHippyControllerProps.ARRAYHippyControllerProps.MAP
  • defaultBoolean:当 defaultType 为 HippyControllerProps.BOOLEAN 时,设置后有效。
  • defaultNumber:当 defaultType 为 HippyControllerProps.NUMBER 时,设置后有效。
  • defaultString:当 defaultType 为 HippyControllerProps.STRING 时,设置后有效。
  1. @HippyControllerProps(name = "text", defaultType = HippyControllerProps.STRING, defaultString = "")
  2. public void setText(MyView textView, String text)
  3. {
  4. textView.setText(text);
  5. }

手势事件处理

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

  1. @Override
  2. public NativeGestureDispatcher getGestureDispatcher()
  3. {
  4. return mGestureDispatcher;
  5. }
  6. @Override
  7. public void setGestureDispatcher(NativeGestureDispatcher dispatcher)
  8. {
  9. mGestureDispatcher = dispatcher;
  10. }
  11. @Override
  12. public boolean onTouchEvent(MotionEvent event)
  13. {
  14. boolean result = super.onTouchEvent(event);
  15. if (mGestureDispatcher != null)
  16. {
  17. result |= mGestureDispatcher.handleTouchEvent(event);
  18. }
  19. return result;
  20. }

注册 HippyViewController

需要在 HippyPackagegetControllers 方法中添加这个Controller,这样它才能在JS中被访问到。

  1. @Override
  2. public List<Class<? extends HippyViewController>> getControllers()
  3. {
  4. List<Class<? extends HippyViewController>> components = new ArrayList<>();
  5. components.add(MyViewController.class);
  6. return components;
  7. }

更多特性

处理组件方法调用

在有些场景,JS需要调用组件的一些方法,比如 MyViewchangeColor。这个时候需要在 HippyViewController重载 dispatchFunction 方法来处理JS的方法调用。

  1. public void dispatchFunction(MyView view, String functionName, HippyArray var)
  2. {
  3. switch (functionName)
  4. {
  5. case "changeColor":
  6. String color = var.getString(0);
  7. view.setColor(Color.parseColor(color));
  8. break;
  9. }
  10. super.dispatchFunction(view, functionName, var);
  11. }

事件回调

Hippy SDK 提供了一个基类 HippyViewEvent,其中封装了UI事件发送的逻辑,只需调用 send 方法即可发送事件到JS对应的组件上。比如我要在 MyView 的 onAttachedToWindow 的时候发送事件到前端的控件上面。 示例如下:

  1. @Override
  2. protected void onAttachedToWindow() {
  3. super.onAttachedToWindow();
  4. // this is show how to send message to js ui
  5. HippyMap hippyMap = new HippyMap();
  6. hippyMap.pushString("test", "code");
  7. new HippyViewEvent(" onAttachedToWindow").send(this, hippyMap);
  8. }

HippyViewController 的回调函数

  • onAfterUpdateProps:属性更新完成后回调。
  • onBatchComplete:一次上屏操作完成后回调(适用于 ListView 类似的组件,驱动 Adapte r刷新等场景)。
  • onViewDestroy:视图被删除前回调(适用于类似回收视图注册的全局监听等场景)。
  • onManageChildComplete:在 HippyGroupController 添加、删除子试图完成后回调。

混淆说明

扩展组件的 Controller 类名和属性设置方法方法名不能混淆,可以增加混淆例外。

  1. -keep class * extends com.tencent.mtt.hippy.uimanager.HippyGroupController{ public *;}
  2. -keep class * extends com.tencent.mtt.hippy.uimanager.HippyViewController{ public *;}