Skip to content

Instantly share code, notes, and snippets.

@nirbhayph
Last active December 11, 2023 21:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nirbhayph/91bc8dae56bf078ff2b007b4a55edc96 to your computer and use it in GitHub Desktop.
Save nirbhayph/91bc8dae56bf078ff2b007b4a55edc96 to your computer and use it in GitHub Desktop.
Google Maps and Jetpack Compose
@Composable
fun CircleMap() {
// Define the coordinates for circle centers and their associated information
val circleData = listOf(
CircleInfo("Park A", LatLng(37.7749, -122.4194), "This is Park A"),
CircleInfo("Park B", LatLng(36.7783, -119.4179), "This is Park B"),
CircleInfo("Park C", LatLng(34.0522, -118.2437), "This is Park C")
)
// Create a mutable state to track the selected circle
var selectedCircle by remember { mutableStateOf<CircleInfo?>(null) }
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(36.7783, -119.4179), 11f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
// Draw clickable circles for each location
circleData.forEach { circleInfo ->
Circle(
center = circleInfo.center,
clickable = true,
fillColor = Color.Blue.copy(alpha = 0.3f),
radius = 5000.0, // Specify the radius in meters
strokeColor = Color.Black,
strokeWidth = 2f,
tag = circleInfo,
onClick = { circle ->
// Handle circle click event
selectedCircle = circle.tag as? CircleInfo
}
)
}
}
// Display information about the selected circle
selectedCircle?.let { circle ->
Box(
contentAlignment = Alignment.TopCenter,
modifier = Modifier.offset(y = 24.dp)
) {
Column(
modifier = Modifier
.wrapContentHeight()
.width(350.dp)
.clip(RoundedCornerShape(10))
.background(Color.DarkGray)
.padding(20.dp)
) {
Text(text = circle.name, style = TextStyle(fontSize = 20.sp))
Spacer(modifier = Modifier.height(8.dp))
Text(text = circle.description, style = TextStyle(fontSize = 16.sp))
}
}
}
}
data class CircleInfo(val name: String, val center: LatLng, val description: String)
@Composable
fun MapScreenWithCustomMarker() {
val philipineSea = LatLng(20.302039, 134.2082661)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(philipineSea, 2f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = MarkerState(position = LatLng(-34.0, 151.0)),
title = "Marker in Sydney"
)
Marker(
state = MarkerState(position = LatLng(35.66, 139.6)),
title = "Marker in Tokyo"
)
MarkerComposable(
state = MarkerState(position = LatLng(11.6600892, 117.3276336)),
) {
Icon(
imageVector = Icons.Filled.Star,
contentDescription = "Philippines",
tint = Color.Blue,
modifier = Modifier.size(64.dp)
)
}
}
}
@Composable
fun MapScreenWithMarkerInfoWindow() {
val philipineSea = LatLng(20.302039, 134.2082661)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(philipineSea, 2f)
}
val markerState = MarkerState(LatLng(14.5892056, 120.9646546))
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
MarkerInfoWindow(
state = markerState,
icon = bitmapDescriptorFromVector(LocalContext.current, R.drawable.baseline_location_city_24)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.border(
BorderStroke(1.dp, Color.Black),
RoundedCornerShape(10)
)
.clip(RoundedCornerShape(10))
.background(Color.Red)
.padding(20.dp)
) {
Icon(
Icons.Filled.Info,
contentDescription = null,
modifier = Modifier.size(36.dp)
)
Text("Manila", fontWeight = FontWeight.Bold)
Text("Capital of the Philippines", fontWeight = FontWeight.Medium)
}
}
}
}
// from stack overflow - https://stackoverflow.com/a/45564994
private fun bitmapDescriptorFromVector(context: Context, vectorResId: Int): BitmapDescriptor? {
return ContextCompat.getDrawable(context, vectorResId)?.run {
setBounds(0, 0, intrinsicWidth, intrinsicHeight)
val bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
draw(Canvas(bitmap))
BitmapDescriptorFactory.fromBitmap(bitmap)
}
}
@Composable
fun MapWithSwitchableProperties() {
val mumbai = LatLng(19.0760, 72.8777)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(mumbai, 11f)
}
var uiSettings by remember { mutableStateOf(MapUiSettings(zoomControlsEnabled = true)) }
var properties by remember {
mutableStateOf(MapProperties(mapType = MapType.TERRAIN))
}
Box(Modifier.fillMaxSize()) {
GoogleMap(
modifier = Modifier.matchParentSize(),
cameraPositionState = cameraPositionState,
properties = properties,
uiSettings = uiSettings
)
Switch(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(vertical = 16.dp),
checked = uiSettings.zoomControlsEnabled,
onCheckedChange = {
uiSettings = uiSettings.copy(zoomControlsEnabled = it)
properties = if (it) {
properties.copy(mapType = MapType.TERRAIN)
} else {
properties.copy(mapType = MapType.SATELLITE)
}
}
)
}
}
@Composable
fun MapScreenWithMarker() {
// change color of the marker
// implement onClick with popup composable
val philipineSea = LatLng(20.302039, 134.2082661)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(philipineSea, 2f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = MarkerState(position = LatLng(-34.0, 151.0)),
title = "Marker in Sydney"
)
Marker(
state = MarkerState(position = LatLng(35.66, 139.6)),
title = "Marker in Tokyo"
)
}
}
@Composable
fun MapScreenWithPhotoMarkers() {
val center = LatLng(38.7319874, -109.7504477)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(center, 10f)
}
val arches = MarkerState(position = LatLng(38.7319874, -109.7504477))
val canyonLands = MarkerState(position = LatLng(38.5348271, -109.816405))
val archesIconState = remember { mutableStateOf<BitmapDescriptor?>(null) }
val canyonIconState = remember { mutableStateOf<BitmapDescriptor?>(null) }
val context = LocalContext.current
LaunchedEffect(key1 = Unit, block = {
archesIconState.value = loadBitmapDescriptorFromUrl(
context,
"https://source.unsplash.com/random/128x128/?arches%20national%20park"
)
canyonIconState.value = loadBitmapDescriptorFromUrl(
context,
"https://source.unsplash.com/random/128x128/?canyon%20national%20park"
)
})
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
archesIconState.value?.let {
Marker(state = arches, icon = it)
}
canyonIconState.value?.let {
Marker(state = canyonLands, icon = it)
}
}
}
suspend fun loadBitmapDescriptorFromUrl(context: Context, imageUrl: String): BitmapDescriptor {
return withContext(Dispatchers.IO) {
Glide.with(context)
.asBitmap()
.load(imageUrl)
.circleCrop()
.submit()
.get()
}
.let { bitmap ->
val resizedBitmap = Bitmap.createScaledBitmap(bitmap, 130, 130, false)
BitmapDescriptorFactory.fromBitmap(resizedBitmap)
}
}
@Composable
fun MapWithPolygon() {
val polygonPoints = listOf(
LatLng(37.7749, -122.4194),
LatLng(37.8049, -122.4400),
LatLng(37.7949, -122.4100)
)
// Create a mutable state to track whether the polygon is selected
var isPolygonSelected by remember { mutableStateOf(false) }
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(37.7749, -122.4194), 13f)
}
) {
Polygon(
points = polygonPoints,
clickable = true,
fillColor = if (isPolygonSelected) Color.Red else Color.Green,
strokeColor = Color.Blue,
strokeWidth = 5f,
tag = "San Francisco",
onClick = { polygon ->
// Handle polygon click event
isPolygonSelected = true
}
)
}
// Add a button to reset the selection
Box(contentAlignment = Alignment.BottomCenter) {
Button(
onClick = {
isPolygonSelected = false
},
modifier = Modifier
.padding(16.dp)
) {
Text("Reset Selection")
}
}
}
@Composable
fun RouteMap() {
// Define the coordinates for a route as a list of LatLng points
val routeCoordinates = listOf(
LatLng(37.7749, -122.4194), // Starting point (e.g., San Francisco)
LatLng(36.7783, -119.4179), // Waypoint 1
LatLng(34.0522, -118.2437), // Waypoint 2 (e.g., Los Angeles)
LatLng(32.7157, -117.1611) // Ending point (e.g., San Diego)
)
// Create a mutable state to track the selected route
var selectedRoute by remember { mutableStateOf<Route?>(null) }
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(LatLng(36.7783, -119.4179), 6f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
// Draw the route polyline
Polyline(
points = routeCoordinates,
clickable = true,
color = Color.Blue,
width = 5f,
tag = CaliforniaRoute,
onClick = { polyline ->
// Handle polyline click event
selectedRoute = polyline.tag as? Route
}
)
}
// Display information about the selected route
selectedRoute?.let { route ->
Box(
contentAlignment = Alignment.TopCenter,
modifier = Modifier.offset(y = 24.dp)
) {
Column(
modifier = Modifier
.wrapContentHeight()
.width(350.dp)
.clip(RoundedCornerShape(10))
.background(Color.DarkGray)
.padding(20.dp)
) {
Text(text = route.name, style = TextStyle(fontSize = 20.sp))
Spacer(modifier = Modifier.height(8.dp))
Text(text = route.description, style = TextStyle(fontSize = 16.sp))
}
}
}
}
data class Route(val name: String, val description: String)
val CaliforniaRoute = Route(
name = "California Road Trip",
description = "Explore the beautiful coast of California on this scenic road trip from San Francisco to San Diego."
)
@Composable
fun MapScreen() {
val mumbai = LatLng(19.0760, 72.8777)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(mumbai, 11f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
)
}
@Composable
fun StreetViewExplorer() {
// Define the location for the Street View Panorama
val constitutionAve = LatLng(38.8921, -77.0067) // Example: DC
StreetView(
streetViewPanoramaOptionsFactory = {
StreetViewPanoramaOptions().position(constitutionAve)
},
isPanningGesturesEnabled = true,
isStreetNamesEnabled = true,
isUserNavigationEnabled = true,
isZoomGesturesEnabled = true
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment