Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.content.res.Configuration
import android.graphics.Bitmap
import android.location.Location
import android.util.Size
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.lifecycle.Lifecycle
Expand Down Expand Up @@ -106,6 +107,7 @@ class GoogleMapsViewImpl(
private val kmlLayersById = mutableMapOf<String, KmlLayer>()
private val urlTileOverlaysById = mutableMapOf<String, TileOverlay>()

private var parentTouchInterceptDisallowed = false
private var cameraMoveReason = -1

val componentCallbacks =
Expand All @@ -123,6 +125,54 @@ class GoogleMapsViewImpl(
}
}

private fun setParentTouchInterceptDisallowed(blocked: Boolean) {
if (parentTouchInterceptDisallowed == blocked) return
parentTouchInterceptDisallowed = blocked
var p = parent
while (p != null) {
p.requestDisallowInterceptTouchEvent(blocked)
p = p.parent
}
}

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if (googleMapsOptions.liteMode == true) return super.dispatchTouchEvent(ev)

val panEnabled = uiSettings?.scrollEnabled == true
val zoomEnabled = uiSettings?.zoomGesturesEnabled == true
val rotateEnabled = uiSettings?.rotateEnabled == true
val tiltEnabled = uiSettings?.tiltEnabled == true

val multiTouchEnabled = zoomEnabled || rotateEnabled || tiltEnabled
val anyMapGestureEnabled = panEnabled || multiTouchEnabled
if (!anyMapGestureEnabled) return super.dispatchTouchEvent(ev)

when (ev.actionMasked) {
MotionEvent.ACTION_DOWN,
MotionEvent.ACTION_MOVE,
MotionEvent.ACTION_POINTER_DOWN,
-> {
val pointers = ev.pointerCount
val shouldBlockParent = pointers >= (if (panEnabled) 1 else 2)
setParentTouchInterceptDisallowed(shouldBlockParent)
}

MotionEvent.ACTION_POINTER_UP -> {
val pointers = ev.pointerCount - 1
val shouldBlockParent = pointers >= (if (panEnabled) 1 else 2)
setParentTouchInterceptDisallowed(shouldBlockParent)
}

MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL,
-> {
setParentTouchInterceptDisallowed(false)
}
}

return super.dispatchTouchEvent(ev)
}

init {
MapsInitializer.initialize(reactContext)
reactContext.registerComponentCallbacks(componentCallbacks)
Expand Down Expand Up @@ -876,6 +926,7 @@ class GoogleMapsViewImpl(
}

override fun onDetachedFromWindow() {
setParentTouchInterceptDisallowed(false)
lifecycleObserver?.let { lifecycle?.removeObserver(it) }
lifecycle = null
super.onDetachedFromWindow()
Expand Down
6 changes: 6 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import LocationScreen from '@src/screens/LocationScreen';
import MarkersScreen from '@src/screens/MarkersScreen';
import PolygonsScreen from '@src/screens/PolygonsScreen';
import PolylinesScreen from '@src/screens/PolylinesScreen';
import ScrollViewScreen from '@src/screens/ScrollViewScreen';
import SnapshotTestScreen from '@src/screens/SnaptshotTestScreen';
import StressTestScreen from '@src/screens/StressTestScreen';
import SvgMarkersScreen from '@src/screens/SvgMarkersScreen';
Expand Down Expand Up @@ -70,6 +71,11 @@ export default function App() {
component={BasicMapScreen}
options={{ title: 'Basic Map' }}
/>
<Stack.Screen
name="ScrollView"
component={ScrollViewScreen}
options={{ title: 'Map in ScrollView' }}
/>
<Stack.Screen
name="Markers"
component={MarkersScreen}
Expand Down
11 changes: 4 additions & 7 deletions example/src/components/MapWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function MapWrapper(props: Props) {
const mapCallbacks = useMapCallbacks(props, props.mapRef, setMapLoaded);

return (
<View style={styles.container}>
<View style={[styles.container, props.style]}>
<GoogleMapsView
{...rest}
initialProps={props.initialProps ?? initialProps}
Expand All @@ -106,7 +106,7 @@ export default function MapWrapper(props: Props) {
trafficEnabled={props.trafficEnabled ?? false}
indoorEnabled={props.indoorEnabled ?? false}
transitEnabled={props.transitEnabled ?? false}
style={[styles.map, props.style]}
style={styles.map}
userInterfaceStyle={
props.userInterfaceStyle ??
(theme.theme === 'dark' ? 'dark' : 'light')
Expand Down Expand Up @@ -134,11 +134,8 @@ const getThemedStyles = (theme: AppTheme) =>
backgroundColor: theme.bgPrimary,
},
map: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
height: '100%',
width: '100%',
},
loadingOverlay: {
...StyleSheet.absoluteFill,
Expand Down
1 change: 1 addition & 0 deletions example/src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {

const screens = [
{ name: 'BasicMap', title: 'Basic Map' },
{ name: 'ScrollView', title: 'Map in ScrollView' },
{ name: 'Markers', title: 'Markers' },
{ name: 'SvgMarkers', title: 'SVG Markers' },
{ name: 'Polygons', title: 'Polygons' },
Expand Down
100 changes: 100 additions & 0 deletions example/src/screens/ScrollViewScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useMemo, useRef } from 'react';

import { Platform, ScrollView, StyleSheet, View } from 'react-native';

import {
type EdgeInsets,
useSafeAreaInsets,
} from 'react-native-safe-area-context';

import MapWrapper from '@src/components/MapWrapper';
import { useAppTheme } from '@src/hooks/useAppTheme';
import type { AppTheme } from '@src/theme';

import type {
GoogleMapsViewRef,
RNLatLng,
} from 'react-native-google-maps-plus';

const LOCATIONS: RNLatLng[] = [
{ latitude: 37.7749, longitude: -122.4194 }, // San Francisco
{ latitude: 40.7128, longitude: -74.006 }, // New York City
{ latitude: 52.52, longitude: 13.405 }, // Berlin
{ latitude: 48.8566, longitude: 2.3522 }, // Paris
{ latitude: 35.6762, longitude: 139.6503 }, // Tokyo
{ latitude: -33.8688, longitude: 151.2093 }, // Sydney
{ latitude: 51.5074, longitude: -0.1278 }, // London
{ latitude: 55.7558, longitude: 37.6173 }, // Moscow
{ latitude: 19.4326, longitude: -99.1332 }, // Mexico City
{ latitude: -23.5505, longitude: -46.6333 }, // São Paulo
];

export default function ScrollViewScreen() {
const theme = useAppTheme();
const layout = useSafeAreaInsets();
const styles = useMemo(() => getThemedStyles(theme, layout), [theme, layout]);
const mapRef = useRef<GoogleMapsViewRef | null>(null);

return (
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.content}
>
{LOCATIONS.map((center, i) => {
const isLite = i % 2 !== 0;
return (
<View key={i} style={styles.card}>
<MapWrapper
mapRef={mapRef}
style={styles.map}
initialProps={{
camera: { center, zoom: 12 },
liteMode: isLite,
}}
uiSettings={
isLite && Platform.OS === 'ios'
? {
allGesturesEnabled: false,
compassEnabled: false,
rotateEnabled: false,
scrollEnabled: false,
scrollDuringRotateOrZoomEnabled: false,
tiltEnabled: false,
zoomGesturesEnabled: false,
}
: undefined
}
mapPadding={{ top: 0, bottom: 0, right: 0, left: 0 }}
/>
</View>
);
})}
</ScrollView>
);
}

const getThemedStyles = (theme: AppTheme, layout: EdgeInsets) =>
StyleSheet.create({
scrollView: {
flex: 1,
backgroundColor: theme.bgPrimary,
},
content: {
padding: 16,
paddingBottom: layout.bottom + 24,
gap: 20,
},
card: {
borderRadius: 10,
overflow: 'hidden',
backgroundColor: theme.bgHeader,
shadowColor: theme.shadow,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 2,
},
map: {
height: 250,
},
});
1 change: 1 addition & 0 deletions example/src/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type RootStackParamList = {
Home: undefined;
Blank: undefined;
BasicMap: undefined;
ScrollView: undefined;
Markers: undefined;
SvgMarkers: undefined;
Polygons: undefined;
Expand Down
Loading