Create a hole in react-native webview for touch events

我只是一个虾纸丫 提交于 2019-12-21 17:42:35

问题


We are trying to repeat the same thing that was done is this plugin: https://github.com/mapsplugin/cordova-plugin-googlemaps/blob/master/README.md (How does this plugin work) but using react-native + mapbox gl(native).

The idea is simple: webview and mapview are "siblings", webview is above mapview and part of webview is transparent and mapview is shown under it. We would like any touch events that occur in this transparent area not to be captured by webview and bubble/whatever to mapview so you can touch/drag/zoom map.

Simply said: we want part(not all of it) of webview not to capture events, but to allow underlying view to capture them.

It looks like there are some methods in react native that allow to do that(conditionally control event capture) (https://facebook.github.io/react-native/docs/view.html#onstartshouldsetrespondercapture ) but we can't find any working example to test it and we can't completely understand documentation that is provided (we can't even understand should this callback be specified for parent view or child views).

So basically we just need some instrument in react-native to conditionally capture touch events.

Can anyone help us with it? Example with map/webview may be too complicated, any conditional capture of events in two views should help a lot.


回答1:


I am not sure if this is the perfect solution but what you can do is to create an EvenEmitter and just make the Webview catch all of the clicks. The ones that should be handled by the Map, can me sent to the map itself.

I use them on screens, where multiple components might be created but they can be emitted to the parent screen. It is mostly used to handle modal screens.

import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';

this._eventEmitter = new EventEmitter();

        this._eventEmitter.addListener('modal', (data) => {
            this.setState({
                visibleModal: true,
                modalData: data
            });
        });

Then you can use them like emitter.emit("modal", data)

Edit:

Here is another approach, which also shows you how you can use the methods you were asking in the question.

class Class extends Component {

    onStartShouldSetResponder = () => true;
    onEvent = (e) => {
        let object = {};
        object.locationX = e.nativeEvent.locationX;
        object.locationY = e.nativeEvent.locationY;
        object.pageY = e.nativeEvent.pageY;
        object.pageX = e.nativeEvent.pageX;
        object.target = e.nativeEvent.target;
        //object.touches = e.nativeEvent.touches; //These will trigger a cyclic error while parsing but you can access them
        //object.changedTouches = e.nativeEvent.changedTouches;
        object.identifier = e.nativeEvent.identifier;
        alert(JSON.stringify(object));

        if (object.pageX > this.state.x && object.pageX < (this.state.x + this.state.width) && object.pageY > this.state.y && object.pageY < (this.state.y + this.state.height))
            alert("inside") //Here you can trigger whatever function you need from the underlying view
    }

    onLayout = (event) => {
        this.setState({
            x: event.nativeEvent.layout.x,
            y: event.nativeEvent.layout.y,
            width: event.nativeEvent.layout.width,
            height: event.nativeEvent.layout.height,
        });
    }

    render(){

        return(    

            <ScrollView>

            <View ref={"target"} style={{
                position: 'absolute',
                height: 200,
                width: 200,
                left: 100,
                top: 100,
                backgroundColor: 'rgba(0,0,0,0.5)'
            }}
            onLayout={this.onLayout}
            />

            <View 
            onl
            onStartShouldSetResponder={this.onStartShouldSetResponder} 
            onResponderMove={this.onEvent}
            style={{
                backgroundColor: 'rgba(255,0,0,0.3)',
                width: '100%',
                height: 150
            }}/>

            <TouchableWithoutFeedback 
            onPress={this.onEvent}
            onLongPress={this.onEvent}
            style={{
                backgroundColor: 'rgba(0,255,0,0.3)',
                width: '100%',
                height: 150
            }}> 
            <View style={{height: 150, backgroundColor: 'rgba(0,255,0,0.3)'}}/>
            </TouchableWithoutFeedback>

            <View 
            onTouchStart={this.onEvent}
            onTouchEnd={this.onEvent}
            style={{
                backgroundColor: 'rgba(0,0,255,0.3)',
                width: '100%',
                height: 150
            }}> 
            </View>

            </ScrollView>

        );
    }

}

Maybe this will help you pass events to the other views



来源:https://stackoverflow.com/questions/48269124/create-a-hole-in-react-native-webview-for-touch-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!