react-native使用nativeID与原生UI交互

644 阅读1分钟

最近在开发一些android原生的功能,深深体会到android原生ui的复杂度真的很高,加上熟练度比较低也不想花费很高的成本去学习,所以想把ReactRootView嵌到进原生activity中去实现一些ui上的交互功能

首先native发送事件给js 一般只会用到NativeEventEmitter已经足够了 写法也很简单

import React, { useEffect } from 'react';
import { NativeModules, NativeEventEmitter } from 'react-native';
import useEvent from './useEvent';

export default function useNativeEvent<T extends any>(
  eventName: string,
  listener: (data: T) => void
) {
  const register = useEvent(() => {
    const EventEmitter = new NativeEventEmitter(NativeModules.MultiBundle);
    return EventEmitter.addListener(eventName, listener);
  });

  useEffect(() => {
    const subject = register();
    return subject.remove;
  }, []);
}
public static void sendEvent(String eventName, Object eventData) {
    ReactContext reactContext = MainApplication.mReactNativeHost.getReactInstanceManager().getCurrentReactContext();
    eventData = RNConvert.convert(eventData);
    if (reactContext != null) {
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,eventData);
    }
}

但是在js上调用原生方法,一般都是通过@ReactMethod注解去实现的,当我在原生的ui上想调用当前activity的方法就会比较恶心,我可能要先在ReactContextBaseJavaModule业务类中实现一个方法,然后通过广播发送出去,再在当前activity中注册一个listener,诸如类的复杂通信方法,会导致代码复杂程度上升,思考了一下,原生可以通过findViewById拿到view后绑定事件,rn应该也可以,然后搜索了一番,具体的实现方式如下:

<TouchableOpacity nativeID="testBtn">
  <View
    style={{
      width: 48,
      height: 48,
      borderRadius: 24,
      backgroundColor: 'red',
    }}></View>
</TouchableOpacity>
import com.facebook.react.uimanager.util.ReactFindViewUtil;

private final ReactFindViewUtil.OnViewFoundListener onTestBtnViewFound = new ReactFindViewUtil.OnViewFoundListener() {
    @Override
    public String getNativeId() {
        return "testBtn";
    }

    @Override
    public void onViewFound(View view) {
       if (view != null) {
           view.setOnTouchListener(new View.OnTouchListener() {
               @Override
               public boolean onTouch(View v, MotionEvent event) {
                   if (event.getAction() == MotionEvent.ACTION_UP) {
                       FaceDetectionActivity.this.finish();
                   }
                   return true;
               }
           });
       }
    }
};


@Override
protected void onStart() {
    super.onStart();
    ReactFindViewUtil.addViewListener(onTestBtnViewFound);
}


@Override
public void finish() {
    super.finish();
    ReactFindViewUtil.removeViewListener(onTestBtnViewFound);
}

这样一来rn中的button调用当前activity中的方法就轻松了很多