Search code examples
androidandroid-jetpack-composegoogle-maps-compose

How to add a floating card beside the start or end point of the route with Google Maps Compose?


So I have created a marker and route with Google Maps which is super easy in Compose:

GoogleMap(
    modifier = Modifier.fillMaxSize(),
    cameraPositionState = cameraPositionState,
    properties = MapProperties(
        isMyLocationEnabled = true
    ),
) {
    Marker(
        state = markerState,
        title = "Drop Off",
    )
    if (route.isNotEmpty()) {
        val bitmapDescriptor = remember {
            bitmapDescriptorFromVector(context, R.drawable.ic_point)
        }
        Polyline(
            points = route,
            color = Color(0xFF1868D2),
            width = 14f,
        )
        Polyline(
            points = route,
            startCap = CustomCap(bitmapDescriptor),
            endCap = CustomCap(bitmapDescriptor),
            color = Color(0xFF00B0FF),
            width = 10f,
        )
    }
 }

But on the design I also have a floating card beside the start and end point of the route which displays some info (time, distance).

How I can implement this type of UI on the map?

enter image description here


Solution

  • Found a solution with MarkerInfoWindow but need to callmarkerState.showInfoWindow() to make it always visible on the map instead of showing it only on a marker click:

    val markerState = rememberMarkerState(
        key = "pickUp",
        position = pickUpLocation
    )
    LaunchedEffect(key1 = markerState) {
        markerState.showInfoWindow()
    }
    LaunchedEffect(key1 = pickUpLocation) {
        markerState.position = pickUpLocation
    }
    MarkerInfoWindow(
        state = markerState,
        title = "Pick Up",
        snippet = "",
        infoWindowAnchor = Offset(-1f, 0.0f),
    ) {
        Card {
            Text(text = "test", color = Color.Black)
        }
    }
    

    Update actually this solution didn't work for me because I need to show two floating cards (pick up and drop off markers) but this solution allows to display only one window for one marker.

    It seems I can't find any other solution how to do it...

    So I guess the only way is to use Marker and convert View to Bitmap to create BitmapDescription from it to set everything as icon

    View solution for Composable Google Maps Marker:

    1. Layout:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#000"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#fff"
            android:text="Test" />
    
    </LinearLayout>
    
    1. View to Bitmap:
    private fun createBitmapFromLayout(view: View): Bitmap {
        val spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
        view.measure(spec, spec)
        view.layout(0, 0, view.measuredWidth, view.measuredHeight)
        val b = Bitmap.createBitmap(
            view.measuredWidth, view.measuredHeight,
            Bitmap.Config.ARGB_8888
        )
        val c = Canvas(b)
        view.draw(c)
        return b
    }
    
    1. In Google Maps composable:
    val context = LocalContext.current
    Marker(
        state = markerState,
        icon = remember {
            View.inflate(context, R.layout.marker_layout, null).let {
                BitmapDescriptorFactory.fromBitmap(createBitmapFromLayout(it))
            }
        }
    )
    

    enter image description here