You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS端react-native-maps用PROVIDER_GOOGLE时Callout onPress无法唤起Modal

iOS端react-native-maps使用谷歌地图时,Callout点击唤起Modal异常的修复方案

问题核心

你遇到的问题根源有两个:

  • 组件层级错误:把Modal嵌套在了Callout内部。在iOS的谷歌地图Provider下,Callout是原生视图容器,而React Native的Modal是顶层组件,嵌套在原生组件里会导致渲染上下文冲突——Alert能触发是因为它是原生系统API,但Modal的渲染会被原生Callout的层级或生命周期干扰,无法正常显示。
  • 重复事件绑定:同时给Marker加了onCalloutPress和Callout加了onPress,这两个事件在谷歌地图iOS端存在触发优先级问题,导致逻辑混乱,出现需要再次点击Marker才能唤起Modal的情况。

修复步骤

  1. 将Modal从Callout内部移出,放到MapView所在的父View中,确保Modal处于正确的React Native组件层级(顶层)。
  2. 移除重复的事件绑定,只保留Marker的onCalloutPress即可(或者只保留Callout的onPress,二选一)。

修改后的完整代码

import React, { useState } from "react";
import { View, StyleSheet, Text, Alert, Modal } from "react-native";
import MapView, { Marker, Callout, PROVIDER_GOOGLE } from "react-native-maps";

const MapBar = ({ coords }) => {
    const [modalVisible, setModal] = useState(false);

    const calloutPress = () => {
        setModal(true);
        Alert.alert("Clicking on the callout");
    };

    return (
        <View style={styles.mapContainer}>
            {/* 把Modal移到这里,和MapView同级 */}
            <Modal
                animationType="slide"
                transparent={true}
                presentationStyle="pageSheet"
                visible={modalVisible}
                onRequestClose={() => setModal(false)}
                onDismiss={() => setModal(false)}
            >
                <View style={styles.centeredView}>
                    <View style={styles.modalView}>
                        <Text style={styles.modalType}></Text>
                        <Text>fezrferger</Text>
                        <Text>fezrferger</Text>
                        <Text>fezrferger</Text>
                    </View>
                </View>
            </Modal>

            <MapView
                provider={PROVIDER_GOOGLE}
                style={styles.map}
                rotateEnabled={false}
                mapType="standard"
                initialRegion={region}
            >
                <Marker
                    coordinate={markerCoordinate}
                    onCalloutPress={calloutPress} {/* 只保留这个事件绑定即可 */}
                >
                    <Callout>
                        <View>
                            <Text style={styles.calloutTitle}>My title</Text>
                            <Text style={styles.calloutDescription}>My description</Text>
                        </View>
                    </Callout>
                </Marker>
            </MapView>
        </View>
    );
};

const region = {
    latitude: 50.846592,
    longitude: 4.352455,
    latitudeDelta: 0.05,
    longitudeDelta: 0.05
};

const markerCoordinate = { latitude: 50.846592, longitude: 4.352455 };

const styles = StyleSheet.create({
    mapContainer: {
        width: "100%",
        height: "100%",
        zIndex: 0
    },
    map: {
        flex: 1
    },
    calloutTitle: {
        fontSize: 17,
        marginBottom: 5,
        fontWeight: "bold"
    },
    calloutDescription: {
        fontSize: 14
    },
    centeredView: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        marginTop: 22,
    },
    modalView: {
        width: '95%',
        margin: 20,
        backgroundColor: "white",
        borderRadius: 20,
        padding: 35,
        justifyContent: "center",
        alignItems: "center",
        shadowColor: "#000",
        shadowOffset: {
            width: 0,
            height: 2
        },
        shadowOpacity: 0.25,
        shadowRadius: 4,
        elevation: 5,
        color: "#777777"
    },
    modalText: {
        marginBottom: 15,
        textAlign: "center",
        color: "#777777"
    }
});

export default MapBar;

额外说明

  • 移到顶层的Modal会被React Native正确渲染在所有视图之上,不会受到谷歌地图原生Callout的限制。
  • 移除重复事件绑定后,点击Callout的逻辑会更清晰,不会出现事件触发冲突的情况。

内容的提问来源于stack exchange,提问作者BenoHiT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:53:20