Coder Social home page Coder Social logo

aasjunior / android-maps-compose Goto Github PK

View Code? Open in Web Editor NEW

This project forked from googlemaps/android-maps-compose

0.0 0.0 0.0 1.23 MB

Jetpack Compose composables for the Maps SDK for Android

Home Page: https://developers.google.com/maps/documentation/android-sdk/maps-compose

License: Apache License 2.0

Kotlin 100.00%

android-maps-compose's Introduction

Tests Stable Discord Apache-2.0

Maps Compose 🗺

Description

This repository contains Jetpack Compose components for the Maps SDK for Android.

Requirements

  • Kotlin-enabled project
  • Jetpack Compose-enabled project (see releases for the required version of Jetpack Compose)
  • An API key
  • API level 21+

Installation

You no longer need to specify the Maps SDK for Android or its Utility Library as separate dependencies, since maps-compose and maps-compose-utils pull in the appropriate versions of these respectively.

dependencies {
    implementation 'com.google.maps.android:maps-compose:3.1.0'
    
    // Optionally, you can include the Compose utils library for Clustering, etc.
    implementation 'com.google.maps.android:maps-compose-utils:3.1.0'

    // Optionally, you can include the widgets library for ScaleBar, etc.
    implementation 'com.google.maps.android:maps-compose-widgets:3.1.0'
}

Sample App

This repository includes a sample app.

To run it:

  1. Get a Maps API key
  2. Create a file in the root directory named local.properties with a single line that looks like this, replacing YOUR_KEY with the key from step 1: MAPS_API_KEY=YOUR_KEY
  3. Build and run

Documentation

You can learn more about all the extensions provided by this library by reading the reference documents.

Usage

Adding a map to your app looks like the following:

val singapore = LatLng(1.35, 103.87)
val cameraPositionState = rememberCameraPositionState {
    position = CameraPosition.fromLatLngZoom(singapore, 10f)
}
GoogleMap(
    modifier = Modifier.fillMaxSize(),
    cameraPositionState = cameraPositionState
)
Creating and configuring a map

Creating and configuring a map

Configuring the map can be done by passing a MapProperties object into the GoogleMap composable, or for UI-related configurations, use MapUiSettings. MapProperties and MapUiSettings should be your first go-to for configuring the map. For any other configuration not present in those two classes, use googleMapOptionsFactory to provide a GoogleMapOptions instance instead. Typically, anything that can only be provided once (i.e. when the map is created)—like map ID—should be provided via googleMapOptionsFactory.

// Set properties using MapProperties which you can use to recompose the map
var mapProperties by remember {
    mutableStateOf(
        MapProperties(maxZoomPreference = 10f, minZoomPreference = 5f)
    )
}
var mapUiSettings by remember {
    mutableStateOf(
        MapUiSettings(mapToolbarEnabled = false)
    )
}
Box(Modifier.fillMaxSize()) {
    GoogleMap(properties = mapProperties, uiSettings = mapUiSettings)
    Column {
        Button(onClick = {
            mapProperties = mapProperties.copy(
                isBuildingEnabled = !mapProperties.isBuildingEnabled
            )
        }) {
            Text(text = "Toggle isBuildingEnabled")
        }
        Button(onClick = {
            mapUiSettings = mapUiSettings.copy(
                mapToolbarEnabled = !mapUiSettings.mapToolbarEnabled
            )
        }) {
            Text(text = "Toggle mapToolbarEnabled")
        }
    }
}

// ...or initialize the map by providing a googleMapOptionsFactory
// This should only be used for values that do not recompose the map such as
// map ID.
GoogleMap(
    googleMapOptionsFactory = {
        GoogleMapOptions().mapId("MyMapId")
    }
)
Controlling a map's camera

Controlling a map's camera

Camera changes and updates can be observed and controlled via CameraPositionState.

Note: CameraPositionState is the source of truth for anything camera related. So, providing a camera position in GoogleMapOptions will be overridden by CameraPosition.

val singapore = LatLng(1.35, 103.87)
val cameraPositionState: CameraPositionState = rememberCameraPositionState {
    position = CameraPosition.fromLatLngZoom(singapore, 11f)
}
Box(Modifier.fillMaxSize()) {
  GoogleMap(cameraPositionState = cameraPositionState)
  Button(onClick = {
    // Move the camera to a new zoom level
    cameraPositionState.move(CameraUpdateFactory.zoomIn())
  }) {
      Text(text = "Zoom In")
  }
}
Drawing on a map

Drawing on a map

Drawing on the map, such as adding markers, can be accomplished by adding child composable elements to the content of the GoogleMap.

GoogleMap(
  //...
) {
    Marker(
        state = MarkerState(position = LatLng(-34, 151)),
        title = "Marker in Sydney"
    )
    Marker(
        state = MarkerState(position = LatLng(35.66, 139.6)),
        title = "Marker in Tokyo"
    )
}

You can also customize the marker you want to add by using MarkerComposable.

val state = MyState()

GoogleMap(
  //...
) {
    MarkerComposable(
        keys = arrayOf(state),
        state = MarkerState(position = LatLng(-34, 151)),
    ) {
        MyCustomMarker(state)
    }
}

As this Composable is backed by a rendering of your Composable into a Bitmap, it will not render your Composable every recomposition. So to trigger a new render of your Composable, you can pass all variables that your Composable depends on to trigger a render whenever one of them change.

Customizing a marker's info window

Customizing a marker's info window

You can customize a marker's info window contents by using the MarkerInfoWindowContent element, or if you want to customize the entire info window, use the MarkerInfoWindow element instead. Both of these elements accept a content parameter to provide your customization in a composable lambda expression.

MarkerInfoWindowContent(
    //...
) { marker ->
    Text(marker.title ?: "Default Marker Title", color = Color.Red)
}

MarkerInfoWindow(
    //...
) { marker ->
    // Implement the custom info window here
    Column {
        Text(marker.title ?: "Default Marker Title", color = Color.Red)
        Text(marker.snippet ?: "Default Marker Snippet", color = Color.Red)
    }
}
Street View

Street View

You can add a Street View given a location using the StreetView composable. To use it, provide a StreetViewPanoramaOptions object as follows:

val singapore = LatLng(1.3588227, 103.8742114)
StreetView(
    streetViewPanoramaOptionsFactory = {
        StreetViewPanoramaOptions().position(singapore)
    }
)
Controlling the map directly (experimental)

Controlling the map directly (experimental)

Certain use cases may require extending the GoogleMap object to decorate / augment the map. It can be obtained with the MapEffect Composable. Doing so can be dangerous, as the GoogleMap object is managed by this library.

GoogleMap(
    // ...
) {
    MapEffect { map ->
        // map is the GoogleMap
    }
}

Utility Library

This library also provides optional utilities in the maps-compose-utils library.

Clustering

The marker clustering utility helps you manage multiple markers at different zoom levels. When a user views the map at a high zoom level, the individual markers show on the map. When the user zooms out, the markers gather together into clusters, to make viewing the map easier.

The MapClusteringActivity demonstrates usage.

Clustering(
    items = items,
    // Optional: Handle clicks on clusters, cluster items, and cluster item info windows
    onClusterClick = null,
    onClusterItemClick = null,
    onClusterItemInfoWindowClick = null,
    // Optional: Custom rendering for clusters
    clusterContent = null,
    // Optional: Custom rendering for non-clustered items
    clusterItemContent = null,
)

Widgets

This library also provides optional composable widgets in the maps-compose-widgets library that you can use alongside the GoogleMap composable.

ScaleBar

This widget shows the current scale of the map in feet and meters when zoomed into the map, changing to miles and kilometers, respectively, when zooming out. A DisappearingScaleBar is also included, which appears when the zoom level of the map changes, and then disappears after a configurable timeout period.

The ScaleBarActivity demonstrates both of these, with the DisappearingScaleBar in the upper left corner and the normal base ScaleBar in the upper right:

maps-compose-scale-bar-cropped

Both versions of this widget leverage the CameraPositionState in maps-compose and therefore are very simple to configure with their defaults:

Box(Modifier.fillMaxSize()) { 
    
    GoogleMap(
        modifier = Modifier.fillMaxSize(),
        cameraPositionState = cameraPositionState
    ) {
        // ... your map composables ...
    }

    ScaleBar(
        modifier = Modifier
            .padding(top = 5.dp, end = 15.dp)
            .align(Alignment.TopEnd),
        cameraPositionState = cameraPositionState
    )

    // OR

    DisappearingScaleBar(
        modifier = Modifier
            .padding(top = 5.dp, end = 15.dp)
            .align(Alignment.TopStart),
        cameraPositionState = cameraPositionState
    )
} 

The colors of the text, line, and shadow are also all configurable (e.g., based on isSystemInDarkTheme() on a dark map). Similarly, the DisappearingScaleBar animations can be configured.

Contributing

Contributions are welcome and encouraged! See contributing for more info.

Support

Encounter an issue while using this library?

If you find a bug or have a feature request, please file an issue. Or, if you'd like to contribute, send us a pull request and refer to our code of conduct.

You can also discuss this library on our Discord server.

android-maps-compose's People

Contributors

arriolac avatar semantic-release-bot avatar dsteve595 avatar kikoso avatar googlemaps-bot avatar wangela avatar barbeau avatar jpoehnelt avatar polivmi1 avatar chibatching avatar adamp avatar claytongreen avatar darrylbayliss avatar mosmb avatar oas004 avatar priyankkjain avatar romainpiel avatar webfrea-k avatar dependabot[bot] avatar lawm avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.