1.RN调用Android原生封装的代码
首先在AS中新建一个类继承自ReactContextBaseJavaModule
代码如下:
public class TestNativeModule extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext;
public TestNativeModule(@Nonnull ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Nonnull
@Override
public String getName() {
//rn通过这个名字调用方法
return "TestNativeModule";
}
//暴露给RN的方法
//函数不能有返回值
@ReactMethod
public void rnCallAndroid(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
AS新建TestReactPackage类继承自ReactPackage
public class TestReactPackage implements ReactPackage {
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
List<NativeModule> list = new ArrayList<>();
list.add(new TestNativeModule(reactContext));
return list;
}
@Nonnull
@Override
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
在MainApplication中getPackages方法中添加刚刚新建的TestReactPackage
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
...
new TestReactPackage(),
...
);
}
AS的内容就完成了,接下来在RN中调用,以一个单击事件为例,代码:
import {NativeModules} from "react-native";
...
<TouchableOpacity
onPress={()=>{NativeModules.TestNativeModule.rnCallAndroid('调用成功!')}} >
<Text>单击调用原生方法</Text>
</TouchableOpacity>
...
2.RN引用Android的控件以及传递参数
引用控件大多是引用一些自定义的控件或者媒体播放器等,首先需要新建一个类继承自SimpleViewManager,这里以引用原生Button为例:
public class ButtonManager extends SimpleViewManager<Button> implements LifecycleEventListener{
public ThemedReactContext mContext;
@Nonnull
@Override
public String getName() {
return "ButtonManager";
}
@Nonnull
@Override
protected Button createViewInstance(@Nonnull ThemedReactContext reactContext) {
this.mContext = reactContext;
this.mContext.addLifecycleEventListener(this);
final Button bn = new Button(reactContext);
bn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建数据传递信使,类似于Android中的Bundle
WritableMap data = Arguments.createMap();
data.putString("msg","点击了bn");// key用于在RN中获取传递的数据
mContext.getJSModule(RCTEventEmitter.class).receiveEvent(
bn.getId(), // RN层原生层根据id绑定在一起
"onClick", // 事件名称
data // 传递的数据
);
}
});
return bn;
}
/** 设置控件属性 rn传入*/
@ReactProp(name = "text")
public void setText(Button view, @Nullable String text) {
view.setText(text);
}
/** 设置控件事件
* 重写getExportedCustomDirectEventTypeConstants
*/
@javax.annotation.Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of("onClick",MapBuilder.of("registrationName", "onClick"));
}
@Override
public void onHostResume() {
}
@Override
public void onHostPause() {
}
@Override
public void onHostDestroy() {
}
}
然后和封装方法一样,需要新建package类集成ReactPackage不过这次是在createViewManagers方法中做修改:
public class ButtonPackage implements ReactPackage {
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Nonnull
@Override
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
List<ViewManager> list = new ArrayList<>();
list.add(new ButtonManager());
return list;
}
}
仍然需要在MainApplication中getPackages方法中添加:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
...
new ButtonPackage(),
...
);
}
再reactnative中需要新建一个js文件将控件导出
AsButton:
import PropTypes from 'prop-types';
import {requireNativeComponent, ViewPropTypes} from 'react-native';
var iface = {
name: 'ButtonManager',
propTypes: {
text: PropTypes.string,
onClick:PropTypes.func,
...ViewPropTypes, // include the default view properties
},
};
module.exports = requireNativeComponent('ButtonManager', iface,{ nativeOnly: { onClick: true }});
在需要引用的地方直接写标签即可:
<ButtonManager
style={{width:50,height:50}}
text={'成功'}
onClick={(event) => {
//接受AS中传递的参数
alert(event.nativeEvent.msg);
}}
/>
单击后的效果:
在AS中写buttonManager的时候没有设置宽高所以有点丑。。