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.

To access to projection we should usedfs MapEffect in order to have access to GoogleMap object

@OptIn(MapsComposeExperimentalApi::class)
@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
){
MapEffect(points) { map ->

}
}
}

Since MapEffect is annotated as experimental, we also must add MapsComposeExperimentalApi annotation

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 inside of our MapEffect

MapEffect(points) { googleMap ->
geoPoints = points.map {
googleMap.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
) {
MapEffect(points) { map ->
geoPoints = points.map {
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 howthis looks:

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

MapEffect(points) { map ->
if (points.isEmpty()) {
geoPoints = emptyList()
} else {
val boundsBuilder = LatLngBounds.Builder()
geoPoints = points.map {
val latLng = map.projection.fromScreenLocation(it)
boundsBuilder.include(latLng)
latLng
}
val bounds = boundsBuilder.build()
}
}

We added empty check because, boundsBuilder.build() will raise an exception we it doesn’t has 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:

Source link