如何在 react native 的新架构中为 android 和 iOS 做事件处理?



我正在尝试创建一个Fabric组件。我已经让它大部分工作了。我面临的唯一问题是我无法获得点击侦听器为fabric组件工作。

我创建了一个规范文件

import type {HostComponent, ViewProps} from 'react-native';
import type {DirectEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
type Event = Readonly<{
value: string;
}>;
interface NativeProps extends ViewProps {
text: string;
onClickHandler?: BubblingEventHandler<Event>; ////Event name should start with on
}
export default codegenNativeComponent<NativeProps>(
'MyButtonView',
) as HostComponent<NativeProps>;

对于android,我的fabric分量如下所示

public class MyButtonView extends androidx.appcompat.widget.AppCompatButton {
public MyButtonView(Context context) {
super(context);
configureViews();
}
private void configureViews(){
setBackgroundColor(Color.YELLOW);
setOnClickListener(view -> {
onReceiveNativeEvent();
});
}
public void onReceiveNativeEvent() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTModernEventEmitter.class)
.receiveEvent(getId(),getId(),"onClickHandler",true,0,event,1);
}
}

不确定在receiveEvent中传递first param as int,canCoalesceEvent,customCoalesceKeycategory

ViewManager中,我也添加了以下代码

@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
Log.i("here55","999999");
return MapBuilder.of("onClickHandler",
MapBuilder.of("registrationName", "onClickHandler")
);
}

对于android,我没有从nativeandroidjs侧获得callback

我遵循https://reactnative.dev/docs/native-components-android,但它是旧的架构,我认为不适用fabric组件

同样的iOShttps://reactnative.dev/docs/native-components-ios,文档不是很有帮助的新架构

对于iOS,我创建了headerobjective-c++文件

通常如果我们想添加属性我们会这样做

RCT_EXPORT_VIEW_PROPERTY(text, NSString)

不确定如何为事件处理程序做

iOS

假设你发布的本地规范是正确的(我不太熟悉TypeScript + Codegen duo)当你在ios/目录下运行pod install命令时,Codegen应该在React-Codegenpod中生成EventEmitterscpp文件(+头)(你可以看到下面如何在XCode中找到它)

链接到带有Pods结构的截图

你可以在你的Objective-C++代码中使用这些类来发出事件:

if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE$$>(_eventEmitter)
->onEvent(facebook::react::$$NAME OF YOUR EVENT EMITTER TYPE::OnEvent{.value = $$VALUE$$});
}

参见下面的链接,看看react-native-screens

是如何完成的
  1. Flow中的本地组件规范
  2. obj - c++代码中的事件发射
  3. 屏幕管理器中的事件曝光-我不太确定这一行是否必要,还没有测试出来。
  4. Android

  1. 要触发编码,只需运行本机构建。
  2. 定义本地事件类,如下所示
  3. 查看如何调度事件
  4. 导出事件类型

确实,文档现在是如此简洁,甚至不确定我是否在使用新的体系结构,但它的工作。

下面是Java风格的Android的步骤。

步骤1 -定义规格

type CustomEvent = Readonly<{
status: string;
}>;
export interface NativeProps extends ViewProps {
onStatusChange?: DirectEventHandler<CustomEvent>;
}

步骤2 -定义事件类

public class CustomEvent extends Event<CustomEvent> {
public static final String EVENT_NAME = "topCustomEvent";
private String status;
CustomEvent(int viewId, String _status) {
super(viewId);
this.status = _status;
}
@Override
public String getEventName() {
return EVENT_NAME;
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
super.dispatch(rctEventEmitter);
}
@Override
protected WritableMap getEventData() {
WritableMap event = Arguments.createMap();
event.putString("status", this.status);
return event;
}
}

步骤3 -通过覆盖其getexporttedcustomdirecteventtypeconstants在ViewManager类中导出/注册事件类型方法。

@Override
public @Nullable
Map getExportedCustomDirectEventTypeConstants() {
Map<String, Object> export = super.getExportedCustomDirectEventTypeConstants();
if (export == null) {
export = MapBuilder.newHashMap();
}
export.put(CustomEvent.EVENT_NAME, MapBuilder.of("registrationName", "onStatusChange"));
return export;
}

步骤4-创建dispatchEvent方法,在需要将事件传递给JS的地方调用它。

private void dispatchEvent(String status) {
EventDispatcher mEventDispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext)this.ctx, getId());
mEventDispatcher.dispatchEvent(new CustomEvent(getId(), status));
}

步骤5 -在JS中设置回调,其中事件将被处理。

onStatusChange={(event) => {console.log('ontatusChange: '+event.nativeEvent.status);}}

步骤6 -构建App, codgen应该像这里解释的那样发生。

最新更新