Displaying LazyRow of ElevatedCards at the bottom of a GoogleMap in Jetpack Compose

2 min read 30-09-2024
Displaying LazyRow of ElevatedCards at the bottom of a GoogleMap in Jetpack Compose


Positioning a LazyRow of ElevatedCards at the Bottom of a Google Map in Jetpack Compose

Imagine you're building a travel app where users can explore nearby attractions. You want to display a list of these attractions, represented by elevated cards, at the bottom of a Google Map. This allows users to easily browse and select points of interest without leaving the map view. This article will guide you through achieving this using Jetpack Compose and Google Maps.

The Problem:

The provided code doesn't work because it attempts to place a LazyRow directly within a GoogleMap. Compose elements are drawn within a hierarchy, and Google Maps is a platform-specific view that cannot directly contain Compose elements.

Code Snippet (Incorrect):

@Composable
fun MapWithCards() {
    GoogleMap(
        modifier = Modifier.fillMaxSize(),
        cameraPositionState = rememberCameraPositionState()
    ) {
        // This will not work! 
        LazyRow(
            modifier = Modifier.align(Alignment.BottomCenter),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(attractions) { attraction ->
                ElevatedCard(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(8.dp)
                ) {
                    // Card content
                }
            }
        }
    }
}

Solution:

To overcome this limitation, we need to use a Compose Box as a container for both the GoogleMap and the LazyRow of ElevatedCards. The Box can then be used to position the LazyRow at the bottom of the screen.

Correct Implementation:

@Composable
fun MapWithCards() {
    Box(modifier = Modifier.fillMaxSize()) {
        GoogleMap(
            modifier = Modifier.matchParentSize(),
            cameraPositionState = rememberCameraPositionState()
        ) {}

        LazyRow(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp)
                .align(Alignment.BottomCenter),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(attractions) { attraction ->
                ElevatedCard(
                    modifier = Modifier
                        .width(150.dp)
                        .padding(8.dp)
                ) {
                    // Card content
                }
            }
        }
    }
}

Explanation:

  1. Box Container: The Box provides a flexible layout container that can hold multiple composables.
  2. GoogleMap: The GoogleMap is positioned within the Box using modifier = Modifier.matchParentSize(). This ensures it takes up the entire space of the parent Box.
  3. LazyRow at Bottom: The LazyRow is positioned using align(Alignment.BottomCenter) and given appropriate padding for visual separation.
  4. ElevatedCards: Each ElevatedCard is placed inside the LazyRow, displaying the attraction details.

Additional Considerations:

  • Data: You'll need to define a data class attraction that holds information about each point of interest.
  • Card Content: Customize the card content with relevant information such as attraction name, image, description, and distance from the user's current location.
  • Map Interactions: Users should be able to interact with the map, such as panning and zooming. Ensure that this interaction doesn't interfere with the display of the cards at the bottom.
  • Responsiveness: Consider how the layout adapts to different screen sizes and orientations.

Useful Resources:

By applying these principles, you can effectively display a LazyRow of ElevatedCards at the bottom of your GoogleMap in Jetpack Compose, enhancing user experience and creating a visually appealing travel app.