react-native-map中CallOut内TouchableOpacity onPress事件失效求助
解决react-native-maps中Marker CallOut内TouchableOpacity onPress不触发的问题
我之前开发的时候也踩过这个坑!react-native-maps的CallOut组件默认的触摸事件处理有个小坑——内部的Touchable组件(比如TouchableOpacity)的点击事件会被父级的Marker或者MapView拦截,导致无法触发。下面给你几个可行的解决办法:
方法一:给CallOut添加空的onPress回调(最简单有效)
只需要在<CallOut>组件上添加一个空的onPress回调,就能阻止事件冒泡到父级,让内部的TouchableOpacity正常响应点击:
<Marker ref={ref => { this.mark = ref; }} coordinate={{ latitude: this.state.lat, longitude: this.state.long }} title={this.state.formatted_address} description='View Details' > {/* 给CallOut添加空的onPress,阻止事件冒泡 */} <CallOut onPress={() => {}}> <View style={{marginTop: 15, flex: 1}}> <Text style={{fontWeight: "bold"}}>{this.state.Title}</Text> </View> <TouchableOpacity style={{marginTop: 15, flex: 1}} onPress={() => {console.log('终于生效了!')}} > <Text style={{fontWeight: "bold"}}>Details</Text> </TouchableOpacity> </CallOut> </Marker>
原理是:CallOut默认会把触摸事件向上传递给Marker/MapView,而添加空的onPress后,CallOut会自己消费这个触摸事件,不再往上传递,内部的Touchable组件就能正常捕获点击了。
方法二:自定义CallOut(完全可控)
如果方法一还是有问题,或者你需要更复杂的交互,可以放弃默认的CallOut,自己实现一个弹窗:
- 给Marker添加
onPress事件,触发显示自定义弹窗 - 用绝对定位的View或者Modal在地图上方展示你的弹窗内容,里面的TouchableOpacity就能正常工作了
示例代码大概是这样:
export default class MapTest extends Component { constructor(props) { super(props); this.state = { showCustomCallout: false } } render() { return ( <View style={{ flex: 1 }}> <MapView style={styles.map} region={{ latitude: this.state.lat, longitude: this.state.long, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} showsUserLocation={true} > <Marker ref={ref => { this.mark = ref; }} coordinate={{ latitude: this.state.lat, longitude: this.state.long }} title={this.state.formatted_address} description='View Details' onPress={() => this.setState({showCustomCallout: true})} /> </MapView> {/* 自定义的CallOut弹窗 */} {this.state.showCustomCallout && ( <View style={{ position: 'absolute', top: 100, left: 50, right: 50, backgroundColor: 'white', padding: 15, borderRadius: 8, shadowColor: '#000', shadowOffset: {width: 0, height: 2}, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5 }}> <Text style={{fontWeight: "bold"}}>{this.state.Title}</Text> <TouchableOpacity style={{marginTop: 15}} onPress={() => { console.log('完美触发!'); this.setState({showCustomCallout: false}); }} > <Text style={{fontWeight: "bold", color: '#007AFF'}}>Details</Text> </TouchableOpacity> </View> )} </View> ); } }
这种方法虽然代码多一点,但完全没有事件冲突的问题,而且你可以自由定制弹窗的样式和交互。
内容的提问来源于stack exchange,提问作者user10254257
相关产品推荐
相关产品推荐

