在gre's answer that put me on the right track, but still left me with a lot of work to do 的基础上,我将尝试解释一些缺失的细节。
有两种基本方法可以做到这一点:
- 使用现有的事件类型
- 创建和使用自定义事件类型
现有事件
正如 gre 提到的,React Native 文档在 Native UI Components section of Events 中对此进行了解释。
他们展示了如何使用以下代码发送事件:
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(), "topChange", event);
有了这个解释:
事件名称topChange映射到onChange回调属性
JavaScript(映射在UIManagerModuleConstants.java)。
UIManagerModuleConstants.java 的实际定义如下所示:
"topChange",
MapBuilder.of(
"phasedRegistrationNames",
MapBuilder.of(
"bubbled", "onChange",
"captured", "onChangeCapture")))
即通过在 Android 代码中使用事件 topChange,您可以在 JS 中使用 onChange 或 onChangeCapture 来拦截它。
您可以在其中找到许多其他已声明的事件以供使用。
其中还声明了“直接”事件可能更有用:
"topLayout",
MapBuilder.of("registrationName", "onLayout")
即Android事件topLayout映射到JS事件回调onLayout
(I do not understand the difference between the "bubbled" vs "captured" vs "direct" event types)
要在 JS 中接收事件,请注意文档中引用了 _onChange() 的 3 个位置:
创建回调方法:_onChange(event: Event) {}
在构造函数中绑定:this._onChange = this._onChange.bind(this);
在创建自定义视图时传递它:return <RCTMyCustomView {...this.props} onChange={this._onChange} />;
自定义事件
自定义事件需要在使用前向系统声明,将Android事件映射到JS事件,类似于上面React Native的处理方式。
这是通过覆盖您的ViewManager 中的以下方法之一来完成的:
getExportedCustomBubblingEventTypeConstants()
getExportedCustomDirectEventTypeConstants()
javadoc 在显示映射应该如何工作方面非常有帮助,但我发现参考上面提到的UIManagerModuleConstants 中的 React Native 代码很有用。
一旦在此处声明,您就可以像使用任何其他“现有”事件一样使用它。
自定义事件实现示例
我想将点击事件从 Android 发送到 JS,并将其命名为 onClick。我选择为此使用“直接”事件。我还选择在 Android 和 JS 中使用相同的名称 - 这不是必需的。
需要修改3个文件:
ViewManager 类
此代码将 Android 事件名称“onClick”映射到 JS 函数“onClick”。
/**
* This method maps the sending of the "onClick" event to the JS "onClick" function.
*/
@Nullable @Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put("onClick",
MapBuilder.of("registrationName", "onClick"))
.build();
}
查看类
当点击视图时,这段代码会向 JS 发送一个事件。此处使用的名称是 Android 事件名称,它将映射到您在上面的 ViewManager 类中设置的任何内容。
// trigger the onPress JS callback
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final Context context = getContext();
if (context instanceof ReactContext) {
((ReactContext) context).getJSModule(RCTEventEmitter.class)
.receiveEvent(getId(),
"onClick", null);
}
}
});
instanceof 检查之所以存在,是因为此视图有时是在 React 上下文之外的本机代码中引用的。
React Native JS 组件
在构造函数中绑定:
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
声明实际的回调函数:
onClick(event: Event) {
// do something
}
请务必set the callback when rendering your view:
render() {
return <NativeView onClick={this.onClick} />;
}
这样的布局非常简单,但更详细的文档分散在网络上。