Free hand draw polygon in Google Maps Compose. Part 2

Rasul Aghakishiyev
ProAndroidDev
Published in
4 min readDec 13, 2023

--

In the previous part we learned how to draw in Jetpack Compose using Canvas API. If you didn’t read it yet, here is the link

Today we will learn how select area in google maps using free hand drawn polygon.

First of all we need add Google Maps dependencies.

implementation("com.google.maps.android:maps-compose:2.11.4")
implementation("com.google.android.gms:play-services-maps:18.2.0")

I will not deep dive into this, you can read more about Maps Compose here:

Now let’s create our map composable

@Composable
fun MyMap(points : List<Point>) {
val losAngeles = LatLng(34.052235, -118.243683)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(losAngeles, 10f)
}
GoogleMap(
modifier = Modifier
.fillMaxSize(),
cameraPositionState = cameraPositionState
){

}
}

There isn’t too much things to describe.

  1. cameraPositionState — used to move camera on the map
  2. points — we will use to draw polygon on the map and later we transform them into real world coordinates.

To transform points into real world coordinates we have class Projection, which has method fromScreenLocation n in Google Maps SDK

We will use this function to transform our screen locations to geographic locations.

We can access to projection from cameraPositionState

@Composable
fun MyMap(points : List<Point>) {
val losAngeles = LatLng(34.052235, -118.243683)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(losAngeles, 10f)
}
GoogleMap(
modifier = Modifier
.fillMaxSize(),
cameraPositionState = cameraPositionState
){
cameraPositionState.projection?.let { projection ->

}
}
}

We also need a state variable to store our transformed points

// We will store our geo points there. We will use them to draw polygon on map
var geoPoints by remember { mutableStateOf(listOf<LatLng>()) }

Now let’s start to transform our coordinates using projection

cameraPositionState.projection?.let { projection ->
geoPoints = points.map {
projection.fromScreenLocation(it)
}
}

You can see, it’s super easy to use.

In order to show polygon on the map, we can use Polygon composable which provided by Maps Compose SDK. So now our code will look like this

@OptIn(MapsComposeExperimentalApi::class)
@Composable
fun MyMap(points: List<Point>) {
val losAngeles = LatLng(34.052235, -118.243683)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(losAngeles, 10f)
}

var geoPoints by remember { mutableStateOf(listOf<LatLng>()) }

GoogleMap(
modifier = Modifier
.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
cameraPositionState.projection?.let { projection ->
geoPoints = points.map {
projection.fromScreenLocation(it)
}
}

if (geoPoints.isNotEmpty()) {
Polygon(
points = geoPoints,
fillColor = Color.Black.copy(alpha = 0.4f)
)
}
}
}

That’s all on map part. Now we should somehow pass points to our map composable. Let’s jump quickly to our MapDrawer composable. Now it looks like this:

First, we need add some variable to store our coordinates. Let’s modify our awaitEachGesture function body and also, we need add callback which will be trigger when drawing finished.

Now we should put these 2 composable together:

@Composable
fun MapsDrawerPage() {
var points by remember { mutableStateOf(listOf<Point>()) }
Box(modifier = Modifier.fillMaxSize()) {
MyMap(points = points)
MapDrawer(
onDrawingEnd = {
points = it
}
)
}
}

Let’s see how this looks:

Now the final part get bounds of this polygon. For this should use LatLngBounds.Builder class. Let’s do some modification

cameraPositionState.projection?.let { projection ->
geoPoints = if (points.isEmpty()) {
emptyList()
} else {
val boundsBuilder = LatLngBounds.Builder()
points.map {
val latLng = projection.fromScreenLocation(
Point(it.x, it.y)
)
boundsBuilder.include(latLng)
latLng
}
}
}

We added empty check because, boundsBuilder.build() will raise an exception if we it don’t have any locations.

The full code

Conclusion

Today learned how to draw polygon on Canvas and transform them into geographic coordinates using Maps Compose SDK.

Feel free to follow me on Twitter and don’t hesitate to ask questions related to Jetpack Compose.

Twitter: https://twitter.com/a_rasul98

Also check out my other post related to Jetpack Compose:

--

--

Android Software Engineer. Interested in mobile development. In love with Jetpack Compose