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

React Native地图切换日期时如何关闭Callout弹窗?

解决React Native Maps切换日期时关闭所有Callout弹窗的问题

在使用react-native-maps开发演出指南应用时,切换日期(点击"Next/Previous day's gigs"按钮)后,需要自动关闭所有当前打开的Callout弹窗,可通过以下方式实现:

核心方案:利用MapView的ref调用deselectAllMarkers()

react-native-maps的MapView组件提供了deselectAllMarkers()方法,调用后会取消所有标记的选中状态,从而自动关闭对应的Callout弹窗。

具体实现步骤:

  1. 创建MapView的ref:使用useRef钩子创建指向MapView的引用。
  2. 修改日期切换函数:在addDays函数中,先调用ref的deselectAllMarkers()方法,再更新日期状态。

修改后的GigMap.js代码:

import { useState, useMemo, useRef } from "react"; // 新增useRef导入
import {
  StyleSheet,
  Text,
  View,
  Pressable,
  Image,
  TouchableOpacity,
} from "react-native";
import MapView from "react-native-maps";
import { Marker, Callout } from "react-native-maps";
import CalloutView from "./CalloutView";
import { mapStyle } from "../util/mapStyle";
import { useGigs } from "../hooks/useGigs";
import { AntDesign } from "@expo/vector-icons";


const GigMap = ({ navigation }) => {
  const [selectedDateMs, setSelectedDateMs] = useState(Date.now());
  const gigs = useGigs();
  const mapRef = useRef(null); // 新增MapView的ref

  // 生成格式为'Dec 20 2022'的日期字符串
  const selectedDateString = useMemo(() => {
    const date = new Date(selectedDateMs);
    const dateToString = date.toString().slice(0,15)
    return dateToString
  }, [selectedDateMs]);


  // 筛选出当日演出
  const gigsToday = gigs.filter((gig) => {
    const gigDate1 = new Date(gig.dateAndTime.seconds*1000)   
    const gigDate2 = gigDate1.toString().slice(0,15)
    return gigDate2 === selectedDateString
  })


  // 增减日期
  const addDays = (amount) => {
    // 先关闭所有Callout弹窗
    if (mapRef.current) {
      mapRef.current.deselectAllMarkers();
    }
    setSelectedDateMs((curr) => curr + 1000 * 60 * 60 * 24 * amount);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.headerText}>{`Gigs on ${selectedDateString}`}</Text>

      <View style={styles.imageText}>
        <Text style = {styles.subHeader}>Tap on</Text>
        <Image
          style={styles.image}
          source={require("../assets/Icon_Gold_48x48.png")}
        />
        <Text style = {styles.subHeader}> to see gig info</Text>
      </View>

      <MapView
        ref={mapRef} // 绑定ref到MapView
        initialRegion={{
          latitude: -41.29416,
          longitude: 174.77782,
          latitudeDelta: 0.03,
          longitudeDelta: 0.03,
        }}
        style={styles.map}
        customMapStyle={mapStyle}
      >
        {gigsToday.map((gig, i) => (
          <Marker
            key={i}
            coordinate={{
              latitude: gig.location.latitude,
              longitude: gig.location.longitude,
            }}
            image={require("../assets/Icon_Gold_48x48.png")}
            description = 'test'
          >
            <Callout
              style={styles.callout}
              tooltip={true}
              onPress={() =>
                navigation.navigate("GigDetails", {
                  venue: gig.venue,
                  date: selectedDateString,
                  gigName: gig.gigName,
                  image: gig.image
                })
              }
            >
              <CalloutView
                venue={gig.venue}
                gigName={gig.gigName}
                genre = {gig.genre}
              />
            </Callout>
          </Marker>
        ))}
      </MapView>

      <View style={styles.buttonOptions}>
        <TouchableOpacity onPress={() => addDays(-1)} style = {styles.touchable}>
          <AntDesign name="caretleft" size={36} color="#778899" />
          <Text style = {{fontFamily:'Helvetica-Neue', color:'#778899'}}>Previous day's gigs</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={() => addDays(1)} style = {styles.touchable}>
          <AntDesign name="caretright" size={36} color="#778899" />
          <Text style = {{fontFamily:'Helvetica-Neue',color:'#778899'}}>Next day's gigs</Text>
        </TouchableOpacity>
      </View>
    </View>

  );
};

原理说明

deselectAllMarkers()是react-native-maps内置方法,会遍历所有标记并取消它们的选中状态。由于Callout弹窗的显示依赖标记的选中状态,标记取消选中后,对应的Callout会自动关闭。这种方式无需额外管理每个标记的状态,简洁高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:50:20