<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Harsh Verma</title>
    <description>The latest articles on Forem by Harsh Verma (@harsh_verma_f5622d6b5d9fa).</description>
    <link>https://forem.com/harsh_verma_f5622d6b5d9fa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3504499%2F1239d03e-398e-4af4-b104-bf4c908baacb.jpg</url>
      <title>Forem: Harsh Verma</title>
      <link>https://forem.com/harsh_verma_f5622d6b5d9fa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/harsh_verma_f5622d6b5d9fa"/>
    <language>en</language>
    <item>
      <title>React Native Maps Marker not Render on Android but work As expected on IOS</title>
      <dc:creator>Harsh Verma</dc:creator>
      <pubDate>Mon, 15 Sep 2025 18:03:22 +0000</pubDate>
      <link>https://forem.com/harsh_verma_f5622d6b5d9fa/react-native-maps-marker-not-render-on-android-but-work-as-expected-on-ios-4i82</link>
      <guid>https://forem.com/harsh_verma_f5622d6b5d9fa/react-native-maps-marker-not-render-on-android-but-work-as-expected-on-ios-4i82</guid>
      <description>&lt;p&gt;I’m using react-native-maps with clustering on the map. When zooming in, markers are displayed with images based on genres. The issue is that the markers are not rendering on Android, although they work as expected on iOS. I’ve tried downgrading to version 1.20.1 and upgrading to the latest version, but the issue persists. I also tried using SVG, PNG, and JPEG formats, but the markers still don’t render. Can someone help me resolve this issue?&lt;br&gt;
&lt;a href="https://drive.google.com/file/d/16fwFJLlIBYz3hH6GErvtQeBrMTSy1G3j/view?usp=sharing" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;`import React, {useRef, useState, useEffect, useMemo, useCallback} from 'react';&lt;br&gt;
import {&lt;br&gt;
  View,&lt;br&gt;
  Text,&lt;br&gt;
  StyleSheet,&lt;br&gt;
  Dimensions,&lt;br&gt;
  Animated,&lt;br&gt;
  PanResponder,&lt;br&gt;
  LayoutChangeEvent,&lt;br&gt;
  ActivityIndicator,&lt;br&gt;
  Platform,&lt;br&gt;
  Image,&lt;br&gt;
  TouchableOpacity,&lt;br&gt;
  ScrollView,&lt;br&gt;
  ViewStyle,&lt;br&gt;
  TextStyleIOS,&lt;br&gt;
  StatusBar,&lt;br&gt;
  ImageBackground,&lt;br&gt;
} from 'react-native';&lt;br&gt;
import {offsetOverlappingCoordinates} from '../utils/offSetSameCoordinate';&lt;br&gt;
import NetInfo from '@react-native-community/netinfo';&lt;br&gt;
import MapView, {Marker, Region} from 'react-native-maps';&lt;br&gt;
import HeaderUser from '../components/HeaderUser';&lt;br&gt;
import EventCard from '../components/EventCard';&lt;br&gt;
import {config} from '../constants/config';&lt;br&gt;
import SearchBottomSheet, {&lt;br&gt;
  SearchBottomSheetRef,&lt;br&gt;
} from '../components/SearchBottomSheet';&lt;br&gt;
import {&lt;br&gt;
  useGetUserNearbyEventsQuery,&lt;br&gt;
  useGetEventByIdQuery,&lt;br&gt;
} from '../services/api/eventApi';&lt;br&gt;
import {useRoute, RouteProp, useNavigation} from '@react-navigation/native';&lt;br&gt;
import {EnumDuration, IEvent, IEventArtist, IGetNearbyEventParams} from '../types.d';&lt;br&gt;
import {getGenreImage, getGenreBackgroundImage} from '../utils/getGenresImage';&lt;br&gt;
import {createClusters} from '../utils/mapScreen';&lt;br&gt;
import {requestUserLocation} from '../utils/locationHelper';&lt;br&gt;
import AppImage from '../components/BaseImage';&lt;/p&gt;

&lt;p&gt;const {height, width} = Dimensions.get('window');&lt;br&gt;
const STATUS_BAR_HEIGHT =&lt;br&gt;
  StatusBar.currentHeight || (Platform.OS === 'ios' ? 44 : 0);&lt;br&gt;
const HEADER_HEIGHT = 80;&lt;br&gt;
const SAFE_TOP_MARGIN = STATUS_BAR_HEIGHT + HEADER_HEIGHT - 70;&lt;br&gt;
const SNAP_BOTTOM = height - 170;&lt;br&gt;
const MAX_SHEET_HEIGHT = height &amp;lt;= 700 ? height * 0.55 : height * 0.65;&lt;br&gt;
const TOP_CONSTRAINT = SAFE_TOP_MARGIN;&lt;/p&gt;

&lt;p&gt;interface EventCoordinate {&lt;br&gt;
  latitude: number;&lt;br&gt;
  longitude: number;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;interface Event {&lt;br&gt;
  id: string;&lt;br&gt;
  name: string;&lt;br&gt;
  image: string;&lt;br&gt;
  end_time?: string;&lt;br&gt;
  date?: string;&lt;br&gt;
  dateRange: string;&lt;br&gt;
  time: string;&lt;br&gt;
  location: string;&lt;br&gt;
  priceRange: string;&lt;br&gt;
  coordinate: EventCoordinate;&lt;br&gt;
  isShare: boolean;&lt;br&gt;
  canLiked: boolean;&lt;br&gt;
  genre: string;&lt;br&gt;
  artist?: IEventArtist[];&lt;br&gt;
  timeFilter: string;&lt;br&gt;
  venue?: IEventArtist[];&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;type RootStackParamList = {&lt;br&gt;
  MapUser: {&lt;br&gt;
    latitude?: number;&lt;br&gt;
    longitude?: number;&lt;br&gt;
    skipApiCall?: boolean;&lt;br&gt;
    eventId?: string;&lt;br&gt;
    showSpecificEvent?: boolean;&lt;br&gt;
  };&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;type MapUserRouteProp = RouteProp;&lt;/p&gt;

&lt;p&gt;const MapScreenUser = () =&amp;gt; {&lt;br&gt;
  const route = useRoute();&lt;br&gt;
  const {&lt;br&gt;
    eventId,&lt;br&gt;
    showSpecificEvent,&lt;br&gt;
    latitude: paramLatitude,&lt;br&gt;
    longitude: paramLongitude,&lt;br&gt;
  } = route.params || {};&lt;/p&gt;

&lt;p&gt;const mapRef = useRef(null);&lt;br&gt;
  const scrollViewRef = useRef(null);&lt;br&gt;
  const scrollY = useRef(0);&lt;br&gt;
  const [locationFetched, setLocationFetched] = useState(false);&lt;br&gt;
  const bottomSheetHeight = useRef(0);&lt;br&gt;
  const isDraggingSheet = useRef(false);&lt;br&gt;
  const isScrolling = useRef(false);&lt;br&gt;
  const [deviceSize, setDeviceSize] = useState({width, height});&lt;br&gt;
  const [singleEventCardHeight, setSingleEventCardHeight] = useState(&lt;br&gt;
    Math.min(250, height * (height &amp;lt;= 700 ? 0.25 : 0.3)),&lt;br&gt;
  );&lt;br&gt;
  const [doubleEventCardHeight, setDoubleEventCardHeight] = useState(&lt;br&gt;
    Math.min(520, height * (height &amp;lt;= 700 ? 0.45 : 0.6)),&lt;br&gt;
  );&lt;br&gt;
  // Update initial region state&lt;br&gt;
  const [region, setRegion] = useState({&lt;br&gt;
    latitude: 51.5074,&lt;br&gt;
    longitude: -0.1278,&lt;br&gt;
    latitudeDelta: showSpecificEvent ? 0.001 : 0.009,&lt;br&gt;
    longitudeDelta: showSpecificEvent ? 0.001 : 0.009,&lt;br&gt;
  });&lt;br&gt;
  const [_userLocation, setUserLocation] = useState(null);&lt;br&gt;
  const [selectedEventIndex, setSelectedEventIndex] = useState(&lt;br&gt;
    null,&lt;br&gt;
  );&lt;br&gt;
  const [isLoading, setIsLoading] = useState(false);&lt;br&gt;
  const [searchQuery, setSearchQuery] = useState('');&lt;br&gt;
  const searchBottomSheetRef = useRef(null);&lt;br&gt;
  const [isConnected, setIsConnected] = useState(true);&lt;br&gt;
  const [showNoResultsMessage, setShowNoResultsMessage] = useState(false);&lt;br&gt;
  const [viewMode, setViewMode] = useState&amp;lt;'clusters' | 'events'&amp;gt;('clusters');&lt;br&gt;
  const [activeClusterIndex, setActiveClusterIndex] = useState(&lt;br&gt;
    null,&lt;br&gt;
  );&lt;br&gt;
  const [visibleEvents, setVisibleEvents] = useState([]);&lt;br&gt;
  const [mapReady, setMapReady] = useState(false);&lt;br&gt;
  const [isSearchActive, setIsSearchActive] = useState(false);&lt;br&gt;
  const [searchResultsCount, setSearchResultsCount] = useState(0);&lt;br&gt;
  const [timeFilters, setTimeFilters] = useState('');&lt;br&gt;
  const [currentZoomLevel, setCurrentZoomLevel] = useState(0.1);&lt;br&gt;
  const navigation = useNavigation();&lt;br&gt;
  const [genreFilters, setGenresFilters] = useState&amp;lt;&lt;br&gt;
    {id: string; name: string}[]&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;([]);&lt;br&gt;
  const [activeFilters] = useState&amp;lt;{&lt;br&gt;
    timeFilters: string[];&lt;br&gt;
    genres: string[];&lt;br&gt;
  }&amp;gt;({&lt;br&gt;
    timeFilters: [],&lt;br&gt;
    genres: [],&lt;br&gt;
  });&lt;br&gt;
  const [filtersApplied] = useState(false);&lt;br&gt;
  const [isInitialMarkerLoad, setIsInitialMarkerLoad] = useState(true);&lt;br&gt;
  const [imageLoadedStates, setImageLoadedStates] = useState&amp;lt;{[key: string]: boolean}&amp;gt;({});  // Track image loads per marker&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;const shouldSkipNearbyEvents = showSpecificEvent &amp;amp;&amp;amp; eventId;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setIsInitialMarkerLoad(true);
const timer = setTimeout(() =&amp;gt; {
  setIsInitialMarkerLoad(false);
}, 1000);
return () =&amp;gt; clearTimeout(timer);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}, [apiEvents, specificEventData, mapIEventToEvent, showSpecificEvent]);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    if (error || specificEventError) {&lt;br&gt;
      console.error('Error fetching events:', error || specificEventError);&lt;br&gt;
      setShowNoResultsMessage(true);&lt;br&gt;
    }&lt;br&gt;
  }, [error, specificEventError]);&lt;/p&gt;

&lt;p&gt;const panY = useRef(new Animated.Value(SNAP_BOTTOM)).current;&lt;br&gt;
  const [isSheetOpen, setIsSheetOpen] = useState(false);&lt;/p&gt;

&lt;p&gt;const clusterArray = useMemo(() =&amp;gt; {&lt;br&gt;
    if (showSpecificEvent) {&lt;br&gt;
      return [];&lt;br&gt;
    }&lt;br&gt;
    return createClusters(filteredEvents, currentZoomLevel);&lt;br&gt;
  }, [filteredEvents, currentZoomLevel, showSpecificEvent]);&lt;/p&gt;

&lt;p&gt;const filteredClusters = useMemo(() =&amp;gt; {&lt;br&gt;
    if (showSpecificEvent || !filtersApplied) {&lt;br&gt;
      return createClusters(events, currentZoomLevel);&lt;br&gt;
    }&lt;br&gt;
    return clusterArray;&lt;br&gt;
  }, [&lt;br&gt;
    events,&lt;br&gt;
    clusterArray,&lt;br&gt;
    filtersApplied,&lt;br&gt;
    currentZoomLevel,&lt;br&gt;
    showSpecificEvent,&lt;br&gt;
  ]);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    if (showSpecificEvent) {&lt;br&gt;
      return;&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (viewMode === 'clusters') {
  setVisibleEvents(filteredEvents);
} else if (activeClusterIndex !== null) {
  const currentCluster = filteredClusters[activeClusterIndex];
  if (currentCluster) {
    setVisibleEvents(currentCluster.events);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}, [&lt;br&gt;
    filtersApplied,&lt;br&gt;
    filteredClusters,&lt;br&gt;
    filteredEvents,&lt;br&gt;
    viewMode,&lt;br&gt;
    activeClusterIndex,&lt;br&gt;
    showSpecificEvent,&lt;br&gt;
  ]);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
    if (filtersApplied &amp;amp;&amp;amp; filteredEvents.length === 0 &amp;amp;&amp;amp; !showSpecificEvent) {&lt;br&gt;
      setShowNoResultsMessage(true);&lt;br&gt;
    } else {&lt;br&gt;
      setShowNoResultsMessage(false);&lt;br&gt;
    }&lt;br&gt;
  }, [filtersApplied, filteredEvents, showSpecificEvent]);&lt;br&gt;
  const expandToFullScreen = () =&amp;gt; {&lt;br&gt;
    Animated.spring(panY, {&lt;br&gt;
      toValue: TOP_CONSTRAINT,&lt;br&gt;
      useNativeDriver: false,&lt;br&gt;
      tension: 70,&lt;br&gt;
      friction: 12,&lt;br&gt;
    }).start(() =&amp;gt; setIsSheetOpen(true));&lt;br&gt;
  };&lt;br&gt;
  const handleClusterPress = (clusterIndex: number) =&amp;gt; {&lt;br&gt;
    if (showSpecificEvent) {&lt;br&gt;
      return;&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setActiveClusterIndex(clusterIndex);
setViewMode('events');
if (isSheetOpen) {
  closeBottomSheet();
  setSelectedEventIndex(null);
}
const cluster = filteredClusters[clusterIndex];
if (mapRef.current) {
  mapRef.current.animateToRegion(
    {
      latitude: cluster.coordinate.latitude,
      longitude: cluster.coordinate.longitude,
      latitudeDelta: 0.03,
      longitudeDelta: 0.03,
    },
    1000,
  );
}
setVisibleEvents(cluster.events);
if (cluster.events.length &amp;gt; 3) {
  expandToFullScreen();
} else {
  openBottomSheet();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleEventMarkerPress = (eventIndex: number) =&amp;gt; {&lt;br&gt;
    setIsLoading(true);&lt;br&gt;
    setSelectedEventIndex(eventIndex);&lt;br&gt;
    const currentEvent = visibleEvents[eventIndex];&lt;br&gt;
    if (mapRef.current) {&lt;br&gt;
      mapRef.current.animateToRegion(&lt;br&gt;
        {&lt;br&gt;
          latitude: currentEvent.coordinate.latitude,&lt;br&gt;
          longitude: currentEvent.coordinate.longitude,&lt;br&gt;
          latitudeDelta: 0.001,&lt;br&gt;
          longitudeDelta: 0.001,&lt;br&gt;
        },&lt;br&gt;
        500,&lt;br&gt;
      );&lt;br&gt;
    }&lt;br&gt;
    const targetHeight = determineBottomSheetHeight();&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Animated.spring(panY, {
  toValue: targetHeight,
  useNativeDriver: false,
  tension: 70,
  friction: 12,
}).start(() =&amp;gt; setIsSheetOpen(true));

setTimeout(() =&amp;gt; {
  setIsLoading(false);
}, 250);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleCenterToUserLocation = async () =&amp;gt; {&lt;br&gt;
    try {&lt;br&gt;
      setIsLoading(true);&lt;br&gt;
      const userRegion = await requestUserLocation();&lt;br&gt;
      setUserLocation(userRegion);&lt;br&gt;
      if (mapRef.current) {&lt;br&gt;
        mapRef.current.animateToRegion(&lt;br&gt;
          {&lt;br&gt;
            latitude: userRegion.latitude,&lt;br&gt;
            longitude: userRegion.longitude,&lt;br&gt;
            latitudeDelta: 0.0009,&lt;br&gt;
            longitudeDelta: 0.0009,&lt;br&gt;
          },&lt;br&gt;
          1000,&lt;br&gt;
        );&lt;br&gt;
      }&lt;br&gt;
    } catch (locationError) {&lt;br&gt;
      console.error('Failed to fetch user location:', locationError);&lt;br&gt;
    } finally {&lt;br&gt;
      setIsLoading(false);&lt;br&gt;
    }&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const handleRegionChange = (region: Region) =&amp;gt; {&lt;br&gt;
    if (showSpecificEvent) {&lt;br&gt;
      return;&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setCurrentZoomLevel(region.latitudeDelta);
if (region.latitudeDelta &amp;gt; 0.05 &amp;amp;&amp;amp; viewMode === 'events') {
  setViewMode('clusters');
  setVisibleEvents(filteredEvents);
  setActiveClusterIndex(null);

  if (isSheetOpen) {
    closeBottomSheet();
    setSelectedEventIndex(null);
  }

  setSelectedEventIndex(null);
} else if (region.latitudeDelta &amp;lt;= 0.04 &amp;amp;&amp;amp; viewMode === 'clusters') {
  let closestClusterIndex = -1;
  let minDistance = Infinity;

  filteredClusters.forEach((cluster, index) =&amp;gt; {
    const distance = Math.sqrt(
      Math.pow(region.latitude - cluster.coordinate.latitude, 2) +
        Math.pow(region.longitude - cluster.coordinate.longitude, 2),
    );

    if (distance &amp;lt; minDistance) {
      minDistance = distance;
      closestClusterIndex = index;
    }
  });
  if (closestClusterIndex !== -1 &amp;amp;&amp;amp; minDistance &amp;lt; 0.02) {
    setActiveClusterIndex(closestClusterIndex);
    setViewMode('events');

    if (isSheetOpen) {
      closeBottomSheet();
      setSelectedEventIndex(null);
    }
    const cluster = filteredClusters[closestClusterIndex];
    setVisibleEvents(cluster.events);
    // Don't automatically open or expand the bottom sheet on zoom
    // This prevents the sheet from opening when zooming in
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleScrollBegin = () =&amp;gt; {&lt;br&gt;
    isScrolling.current = true;&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const handleScrollEnd = () =&amp;gt; {&lt;br&gt;
    isScrolling.current = false;&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const handleScroll = (event: any) =&amp;gt; {&lt;br&gt;
    scrollY.current = event.nativeEvent.contentOffset.y;&lt;br&gt;
    const eventsToShow = isSearchActive&lt;br&gt;
      ? events.filter(event =&amp;gt; {&lt;br&gt;
          const lowercaseQuery = searchQuery.toLowerCase();&lt;br&gt;
          return (&lt;br&gt;
            event.location.toLowerCase().includes(lowercaseQuery) ||&lt;br&gt;
            event.name.toLowerCase().includes(lowercaseQuery)&lt;br&gt;
          );&lt;br&gt;
        })&lt;br&gt;
      : filtersApplied&lt;br&gt;
      ? filteredEvents&lt;br&gt;
      : viewMode === 'events'&lt;br&gt;
      ? visibleEvents&lt;br&gt;
      : events;&lt;br&gt;
    if (&lt;br&gt;
      eventsToShow.length &amp;gt; 3 &amp;amp;&amp;amp;&lt;br&gt;
      isSheetOpen &amp;amp;&amp;amp;&lt;br&gt;
      selectedEventIndex === null &amp;amp;&amp;amp;&lt;br&gt;
      !showSpecificEvent&lt;br&gt;
    ) {&lt;br&gt;
      expandToFullScreen();&lt;br&gt;
    }&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const handleBottomSheetLayout = (event: LayoutChangeEvent) =&amp;gt; {&lt;br&gt;
    bottomSheetHeight.current = event.nativeEvent.layout.height;&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const panResponder = useRef(&lt;br&gt;
    PanResponder.create({&lt;br&gt;
      onMoveShouldSetPanResponder: (evt, gestureState) =&amp;gt; {&lt;br&gt;
        const isSignificantVerticalGesture =&lt;br&gt;
          Math.abs(gestureState.dy) &amp;gt; 10 &amp;amp;&amp;amp;&lt;br&gt;
          Math.abs(gestureState.dy) &amp;gt; Math.abs(gestureState.dx);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if (!isSignificantVerticalGesture) {
      return false;
    }
    const isDraggingHandle = evt.nativeEvent.locationY &amp;lt; 60;
    const isAtTopOfScrollView = scrollY.current &amp;lt;= 0;
    const isDraggingDown = gestureState.dy &amp;gt; 0;

    return isDraggingHandle || (isAtTopOfScrollView &amp;amp;&amp;amp; isDraggingDown);
  },
  onPanResponderGrant: () =&amp;gt; {
    panY.setOffset(panY._value);
    panY.setValue(0);
    isDraggingSheet.current = true;
  },
  onPanResponderMove: (_, gestureState) =&amp;gt; {
    let newY = gestureState.dy;
    const minHeight = determineBottomSheetHeight();
    const maxHeight = SNAP_BOTTOM;
    const currentPosition = panY._offset + newY;
    if (currentPosition &amp;lt; minHeight) {
      newY = minHeight - panY._offset;
    } else if (currentPosition &amp;gt; maxHeight) {
      newY = maxHeight - panY._offset;
    }

    panY.setValue(newY);
  },
  onPanResponderRelease: (_, gestureState) =&amp;gt; {
    panY.flattenOffset();
    isDraggingSheet.current = false;

    const currentPosition = panY._value;
    const velocity = gestureState.vy;
    const shouldOpen =
      velocity &amp;lt; -0.3 ||
      (velocity &amp;gt; -0.3 &amp;amp;&amp;amp;
        velocity &amp;lt; 0.3 &amp;amp;&amp;amp;
        currentPosition &amp;lt; SNAP_BOTTOM / 2);
    const targetValue = shouldOpen
      ? determineBottomSheetHeight()
      : SNAP_BOTTOM;

    Animated.spring(panY, {
      toValue: targetValue,
      useNativeDriver: false,
      tension: 70,
      friction: 12,
    }).start(() =&amp;gt; {
      setIsSheetOpen(shouldOpen);
    });
  },
  onPanResponderTerminate: (_, _gestureState) =&amp;gt; {
    panY.flattenOffset();
    isDraggingSheet.current = false;

    const currentPosition = panY._value;
    const shouldOpen = currentPosition &amp;lt; SNAP_BOTTOM / 2;
    const targetValue = shouldOpen
      ? determineBottomSheetHeight()
      : SNAP_BOTTOM;

    Animated.spring(panY, {
      toValue: targetValue,
      useNativeDriver: false,
      tension: 70,
      friction: 12,
    }).start(() =&amp;gt; {
      setIsSheetOpen(shouldOpen);
    });
  },
}),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;).current;&lt;/p&gt;

&lt;p&gt;const handleEventCardLayout = (event: LayoutChangeEvent) =&amp;gt; {&lt;br&gt;
    const {height: cardHeight} = event.nativeEvent.layout;&lt;br&gt;
    const isSmallDevice = deviceSize.height &amp;lt;= 700;&lt;br&gt;
    const newSingleCardHeight = Math.min(&lt;br&gt;
      cardHeight + 32,&lt;br&gt;
      deviceSize.height * (isSmallDevice ? 0.25 : 0.3),&lt;br&gt;
    );&lt;br&gt;
    setSingleEventCardHeight(newSingleCardHeight);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const newDoubleCardHeight = Math.min(
  cardHeight * 2 + 64,
  deviceSize.height * (isSmallDevice ? 0.45 : 0.6),
);
setDoubleEventCardHeight(newDoubleCardHeight);
if (isSheetOpen) {
  const targetHeight = determineBottomSheetHeight();
  Animated.spring(panY, {
    toValue: targetHeight,
    useNativeDriver: false,
    tension: 70,
    friction: 12,
  }).start();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleEventCountTextPress = () =&amp;gt; {&lt;br&gt;
    if (filtersApplied &amp;amp;&amp;amp; filteredEvents.length === 0) {&lt;br&gt;
      return;&lt;br&gt;
    }&lt;br&gt;
    if (showSpecificEvent) {&lt;br&gt;
      return;&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setSelectedEventIndex(null);
const eventsToShow = isSearchActive
  ? events.filter(event =&amp;gt; {
      const lowercaseQuery = searchQuery.toLowerCase();
      return (
        event.location.toLowerCase().includes(lowercaseQuery) ||
        event.name.toLowerCase().includes(lowercaseQuery)
      );
    })
  : filtersApplied
  ? filteredEvents
  : viewMode === 'events'
  ? visibleEvents
  : events;
if (eventsToShow.length &amp;gt; 3) {
  expandToFullScreen();
} else {
  openBottomSheet();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleSearch = () =&amp;gt; {&lt;br&gt;
    if (!searchQuery) {&lt;br&gt;
      setIsSearchActive(false);&lt;br&gt;
    }&lt;br&gt;
    searchBottomSheetRef.current?.open();&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;const handleSelectSearchResult = (result: string) =&amp;gt; {&lt;br&gt;
    setSearchQuery(result);&lt;br&gt;
    setIsSearchActive(true);&lt;br&gt;
    let matchedEvents = 0;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (result) {
  const lowercaseResult = result.toLowerCase();
  matchedEvents = events.filter(
    event =&amp;gt;
      event.location.toLowerCase().includes(lowercaseResult) ||
      event.name.toLowerCase().includes(lowercaseResult),
  ).length;
}

setSearchResultsCount(matchedEvents);

if (matchedEvents &amp;gt; 0) {
  setSelectedEventIndex(null);
  if (matchedEvents &amp;gt; 3) {
    expandToFullScreen();
  } else {
    openBottomSheet();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;};&lt;/p&gt;

&lt;p&gt;const handleMapReady = () =&amp;gt; {&lt;br&gt;
    setMapReady(true); // Trigger image re-render&lt;br&gt;
  };&lt;/p&gt;

&lt;p&gt;// Fallback image source&lt;br&gt;
  const defaultGenreImage = {uri: '&lt;a href="https://via.placeholder.com/66'" rel="noopener noreferrer"&gt;https://via.placeholder.com/66'&lt;/a&gt;};&lt;/p&gt;

&lt;p&gt;const getSafeGenreImage = useCallback((genre: string) =&amp;gt; {&lt;br&gt;
    const imageSource = getGenreImage(genre);&lt;br&gt;
    if (!imageSource || (typeof imageSource === 'object' &amp;amp;&amp;amp; !imageSource.uri)) {&lt;br&gt;
      console.warn(&lt;code&gt;Invalid genre image for ${genre}, using default&lt;/code&gt;);&lt;br&gt;
      return defaultGenreImage;&lt;br&gt;
    }&lt;br&gt;
    return imageSource;&lt;br&gt;
  }, []);&lt;/p&gt;

&lt;p&gt;const getSafeGenreBackgroundImage = useCallback((genre: string) =&amp;gt; {&lt;br&gt;
    const backgroundImage = getGenreBackgroundImage(genre);&lt;br&gt;
    if (&lt;br&gt;
      !backgroundImage ||&lt;br&gt;
      (typeof backgroundImage === 'object' &amp;amp;&amp;amp; !backgroundImage.uri)&lt;br&gt;
    ) {&lt;br&gt;
      console.warn(&lt;br&gt;
        &lt;code&gt;Invalid genre background image for ${genre}, using checkmap fallback&lt;/code&gt;,&lt;br&gt;
      );&lt;br&gt;
      return require('../assets/checkmap.png'); // fallback to your original image&lt;br&gt;
    }&lt;br&gt;
    return backgroundImage;&lt;br&gt;
  }, []);&lt;/p&gt;

&lt;p&gt;const currentEvent =&lt;br&gt;
    selectedEventIndex !== null &amp;amp;&amp;amp; viewMode === 'events'&lt;br&gt;
      ? visibleEvents[selectedEventIndex]&lt;br&gt;
      : null;&lt;/p&gt;

&lt;p&gt;const visibleEventsCount = filteredEvents.length;&lt;/p&gt;

&lt;p&gt;const isLoadingEvents = showSpecificEvent&lt;br&gt;
    ? isFetchingSpecificEvent&lt;br&gt;
    : isFetchingEvents;&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;br&gt;
      {isLoading &amp;amp;&amp;amp; !locationFetched &amp;amp;&amp;amp; (&lt;br&gt;
        &lt;br&gt;
          &lt;br&gt;
          Getting your location...&lt;br&gt;
        &lt;br&gt;
      )}&lt;br&gt;
      
        barStyle="dark-content"&lt;br&gt;
        backgroundColor="transparent"&lt;br&gt;
        translucent={true}&lt;br&gt;
      /&amp;gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;MapView
    ref={mapRef}
    style={[
      StyleSheet.absoluteFillObject,
      styles.map,
      !isConnected &amp;amp;&amp;amp; styles.mapOffline,
    ]}
    initialRegion={{
      latitude: region?.latitude || 51.5074,
      longitude: region?.longitude || -0.1278,
      latitudeDelta: showSpecificEvent ? 0.001 : 0.009,
      longitudeDelta: showSpecificEvent ? 0.001 : 0.009,
    }}
    onMapReady={handleMapReady}
    onRegionChangeComplete={handleRegionChange}
    showsUserLocation={false}
    showsMyLocationButton={false}
    showsCompass={false}
    showsScale={false}
    showsBuildings={false}
    showsIndoors={false}
    toolbarEnabled={false}
    loadingEnabled={false}
    moveOnMarkerPress={false}&amp;gt;
    {mapReady &amp;amp;&amp;amp;
      isConnected &amp;amp;&amp;amp;
      viewMode === 'clusters' &amp;amp;&amp;amp;
      !showSpecificEvent &amp;amp;&amp;amp;
      filteredClusters.map((cluster, index) =&amp;gt; (
        &amp;lt;Marker
          key={`cluster-${index}`}
          ref={ref =&amp;gt; (markerRefs.current[`cluster-${index}`] = ref)}  // Add ref
          coordinate={cluster.coordinate}
          onPress={() =&amp;gt; handleClusterPress(index)}
          tracksViewChanges={isInitialMarkerLoad}&amp;gt;
          &amp;lt;View style={styles.markerContainer}&amp;gt;
            &amp;lt;View style={styles.clusterMarkerCircle}&amp;gt;
              &amp;lt;Text style={styles.markerText}&amp;gt;{cluster.count}&amp;lt;/Text&amp;gt;
            &amp;lt;/View&amp;gt;
            &amp;lt;View style={styles.markerTip} /&amp;gt;
          &amp;lt;/View&amp;gt;
        &amp;lt;/Marker&amp;gt;
      ))}

    {mapReady &amp;amp;&amp;amp;
      isConnected &amp;amp;&amp;amp;
      (viewMode === 'events' || showSpecificEvent) &amp;amp;&amp;amp;
      (() =&amp;gt; {
        const adjustedCoordinates =
          offsetOverlappingCoordinates(visibleEvents);
        return visibleEvents.map((event, index) =&amp;gt; {
          const isSelected = index === selectedEventIndex;
          const isZoomedIn = currentZoomLevel &amp;lt;= 0.02 || showSpecificEvent;
          const showCallout = isSelected || isZoomedIn;
          return (
            &amp;lt;Marker
              key={`event-${event.id}`}
              coordinate={adjustedCoordinates[index]}
              onPress={() =&amp;gt; handleEventMarkerPress(index)}
              tracksViewChanges={isInitialMarkerLoad || showCallout}&amp;gt;
              &amp;lt;View style={styles.markerContainer}&amp;gt;
                {showCallout ? (
                  &amp;lt;View style={styles.calloutContainer}&amp;gt;
                    &amp;lt;View style={styles.heartIconContainer}&amp;gt;
                      &amp;lt;AppImage
                        source={getSafeGenreImage(event.genre)}
                        style={styles.heartIcon}
                        resizeMode="contain"
                        fallbackSource={require('../assets/genres/Blues.png')}
                      /&amp;gt;
                    &amp;lt;/View&amp;gt;
                    &amp;lt;ImageBackground
                      source={getSafeGenreBackgroundImage(event.genre)}
                      style={styles.calloutBackground}&amp;gt;
                      &amp;lt;Text style={styles.calloutText}&amp;gt;{event.name}&amp;lt;/Text&amp;gt;
                      {event.artist?.map((artist, artistIndex) =&amp;gt; (
                        &amp;lt;Text key={`artist-${artistIndex}`} style={styles.calloutText}&amp;gt;
                          {artist.name}
                        &amp;lt;/Text&amp;gt;
                      ))}
                      {event.venue?.map((venue, venueIndex) =&amp;gt; (
                        &amp;lt;Text key={`venue-${venueIndex}`} style={styles.calloutText}&amp;gt;
                          {venue.name}
                        &amp;lt;/Text&amp;gt;
                      ))}
                    &amp;lt;/ImageBackground&amp;gt;
                  &amp;lt;/View&amp;gt;
                ) : (
                  &amp;lt;&amp;gt;
                    &amp;lt;View
                      style={[
                        styles.markerCircle,
                        isSelected &amp;amp;&amp;amp; styles.selectedMarkerCircle,
                      ]}&amp;gt;
                      &amp;lt;Text
                        style={[
                          styles.markerText,
                          isSelected &amp;amp;&amp;amp; styles.selectedMarkerText,
                        ]}&amp;gt;
                        {1}
                      &amp;lt;/Text&amp;gt;
                    &amp;lt;/View&amp;gt;
                    &amp;lt;View style={styles.markerTip} /&amp;gt;
                  &amp;lt;/&amp;gt;
                )}
              &amp;lt;/View&amp;gt;
            &amp;lt;/Marker&amp;gt;
          );
        });
      })()}
  &amp;lt;/MapView&amp;gt;

  &amp;lt;View style={styles.headerContainer}&amp;gt;
    &amp;lt;HeaderUser
      title="Map"
      showSearchBar={!showSpecificEvent}
      showBackButton={showSpecificEvent}
      onBackPress={handleBackPress}
      searchPlaceholder="Event Name"
      searchQuery={searchQuery}
      setSearchQuery={setSearchQuery}
      setTimeFilters={setTimeFilters}
      timeFilters={timeFilters}
      genresFilter={genreFilters}
      setGenresFilters={setGenresFilters}
      onSearch={handleSearch}
    /&amp;gt;





  &amp;lt;TouchableOpacity
    style={styles.locationButton}
    onPress={handleCenterToUserLocation}
    disabled={isLoading}&amp;gt;
    &amp;lt;Image
      source={require('../assets/gps.png')}
      style={styles.locationIcon}
    /&amp;gt;
  &amp;lt;/TouchableOpacity&amp;gt;

  &amp;lt;Animated.View
    style={[
      styles.bottomSheet,
      {
        transform: [{translateY}],
        zIndex: dynamicZIndex,
        ...Platform.select({
          android: {elevation},
        }),
      },
    ]}
    onLayout={handleBottomSheetLayout}&amp;gt;




        &amp;lt;ScrollView
          ref={scrollViewRef}
          onLayout={event =&amp;gt; {
            if (
              event.nativeEvent.layout.height &amp;gt; 0 &amp;amp;&amp;amp;
              doubleEventCardHeight === 520
            ) {
              const isSmallDevice = deviceSize.height &amp;lt;= 700;
              setDoubleEventCardHeight(
                Math.min(
                  event.nativeEvent.layout.height,
                  deviceSize.height * (isSmallDevice ? 0.45 : 0.6),
                ),
              );
            }
          }}
          style={styles.eventCardsList}
          contentContainerStyle={styles.scrollViewContent}
          showsVerticalScrollIndicator={true}
          onScrollBeginDrag={handleScrollBegin}
          onScrollEndDrag={handleScrollEnd}
          onMomentumScrollBegin={handleScrollBegin}
          onMomentumScrollEnd={handleScrollEnd}
          onScroll={handleScroll}
          scrollEventThrottle={16}
          nestedScrollEnabled={true}
          scrollEnabled={!isDraggingSheet.current}
          bounces={true}
          alwaysBounceVertical={false}&amp;gt;
          {(() =&amp;gt; {
            const eventsToShow = showSpecificEvent
              ? events
              : isSearchActive
              ? events.filter(event =&amp;gt; {
                  const lowercaseQuery = searchQuery.toLowerCase();
                  return (
                    event.location.toLowerCase().includes(lowercaseQuery) ||
                    event.name.toLowerCase().includes(lowercaseQuery)
                  );
                })
              : filtersApplied
              ? filteredEvents
              : viewMode === 'events'
              ? visibleEvents
              : events;

            if (eventsToShow.length === 0) {
              return (
                &amp;lt;Text style={styles.noEventsText}&amp;gt;No events found&amp;lt;/Text&amp;gt;
              );
            } else if (eventsToShow.length === 1) {
              const singleEvent = eventsToShow[0];
              return (
                &amp;lt;View onLayout={handleEventCardLayout}&amp;gt;
                  &amp;lt;EventCard
                    id={singleEvent.id || ''}
                    name={singleEvent.name}
                    image={singleEvent.image}
                    date={singleEvent.date || singleEvent.dateRange || ''}
                    endTime={singleEvent.end_time || ''}
                    time={singleEvent.time}
                    location={singleEvent.location}
                    priceRange={singleEvent.priceRange}
                    isShare={singleEvent.isShare}
                    canLiked={singleEvent.canLiked}
                  /&amp;gt;
                &amp;lt;/View&amp;gt;
              );
            }
            return eventsToShow.map((event, index) =&amp;gt; (
              &amp;lt;View
                key={`event-card-${event.id}`}
                style={styles.eventCardContainer}
                onLayout={index === 0 ? handleEventCardLayout : undefined}&amp;gt;
                &amp;lt;EventCard
                  id={event.id || ''}
                  name={event.name}
                  image={event.image}
                  date={event.date || event.dateRange || ''}
                  endTime={event.end_time || ''}
                  time={event.time}
                  location={event.location}
                  priceRange={event.priceRange}
                  type="customer"
                  isShare={event.isShare}
                  canLiked={event.canLiked}
                /&amp;gt;
              &amp;lt;/View&amp;gt;
            ));
          })()}
          &amp;lt;View style={{height: 100}} /&amp;gt;
        &amp;lt;/ScrollView&amp;gt;
      )
    ) : null}
  &amp;lt;/Animated.View&amp;gt;

  {!showSpecificEvent &amp;amp;&amp;amp; (
    &amp;lt;SearchBottomSheet
      ref={searchBottomSheetRef}
      onSelectResult={handleSelectSearchResult}
      searchQuery={searchQuery}
      setSearchQuery={setSearchQuery}
    /&amp;gt;
  )}
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;);&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;export default MapScreenUser;&lt;br&gt;
`&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>android</category>
      <category>programming</category>
      <category>node</category>
    </item>
  </channel>
</rss>
