React Native Android Native UI 组件中的自定义事件

2022-09-03 07:44:44

我想在Android上的React Native应用程序中使用OpenStreetMap磁贴,所以我正在尝试包装OSMDroid原生UI组件,如此处所述。在大多数情况下,它工作正常,但我很难弄清楚如何正确处理事件,特别是和。onScrollonZoom

使用OSMDroid,您可以设置一个延迟的MapListener来处理事件,这非常简单。我已经确认在Java端正确处理事件,直到应该触发JS代码为止。但是,它们不会触发我的JavaScript代码。

根据文档,我已经在我的视图管理器的方法中实现了Java中的事件处理程序:createViewInstance

map.setMapListener(new DelayedMapListener(new MapListener() {
    public boolean onScroll(ScrollEvent event) {
        WritableMap eventData = Arguments.createMap();

        // Fill in eventData; details not important

        ReactContext reactContext = (ReactContext)map.getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
            map.getId(),
            "topChange",
             eventData);

        return true;
    }

    public boolean onZoom(ZoomEvent event) {
        // Basically the same as above
    }
}, 100));

我的JS代码的相关部分与上面链接的文档中的代码基本相同:

class OSMDroidMapView extends Component {
    constructor(props) {
        super(props);
        this._onChange = this._onChange.bind(this);
    }

    _onChange(event: Event) {
        console.log(event);
        // Handle event data
    }

    render() {
        return <OSMDroidMapView {...this.props} onChange={this._onChange}/>
    }
}

没有任何错误或任何迹象表明有任何错误。正确调用 Java 事件处理程序代码。当事件发生时,JS代码中没有发生任何事情的迹象。有谁知道如何正确地做到这一点?我觉得我一定错过了一些基本概念。


答案 1

要将自定义事件发送到 Javascript,您可以使用 RCTDeviceEventEmitter:

在原生端:

import com.facebook.react.modules.core.DeviceEventManagerModule;

...

public boolean onScroll(ScrollEvent event) {
    WritableMap eventData = Arguments.createMap();

    // Fill in eventData; details not important

    ReactContext reactContext = (ReactContext)map.getContext();
    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("YouCustomEventName", eventData);

    return true;
}

在JS模块中,你只需要使用DeviceEventEmitter注册一个监听器:

class OSMDroidMapView extends Component {
    constructor(props) {
        super(props);
        this._onChange = this._onChange.bind(this);
    }

    componentWillMount() {
        DeviceEventEmitter.addListener('YouCustomEventName', this._onChange);
    }

    componentWillUnmount() {
        DeviceEventEmitter.removeListener('YouCustomEventName', this._onChange);
    }

    _onChange(event: Event) {
        console.log(event);
        // Handle event data
    }

    render() {
        return <OSMDroidMapView {...this.props} onChange={this._onChange}/>
    }
}

希望它有帮助。


答案 2