Skip to content

Commit

Permalink
feat: add support for Advanced Markers (#440)
Browse files Browse the repository at this point in the history
* update dependency to maps-ktx and maps-utils-ktx 5.0.0
* transitively, update to Maps SDK for Android v18.2.0 with the upgraded renderer https://developers.google.com/maps/documentation/android-sdk/release-notes#October_18_2023

---------

Co-authored-by: Angela Yu <5506675+wangela@users.noreply.github.com>
  • Loading branch information
kikoso and wangela committed Oct 28, 2023
1 parent d299486 commit d949465
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 41 deletions.
43 changes: 25 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,38 +159,44 @@ composable elements to the content of the `GoogleMap`.

```kotlin
GoogleMap(
//...
googleMapOptionsFactory = {
GoogleMapOptions().mapId("DEMO_MAP_ID")
},
//...
) {
Marker(
AdvancedMarker(
state = MarkerState(position = LatLng(-34, 151)),
title = "Marker in Sydney"
)
Marker(
AdvancedMarker(
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`.
You can customize a marker by using `PinConfig` with an `AdvancedMarker`.

```kotlin
val state = MyState()

GoogleMap(
//...
googleMapOptionsFactory = {
GoogleMapOptions().mapId("DEMO_MAP_ID")
},
//...
) {
MarkerComposable(
keys = arrayOf(state),
val pinConfig = PinConfig.builder()
.setBackgroundColor(Color.MAGENTA)
.build()

AdvancedMarker(
state = MarkerState(position = LatLng(-34, 151)),
) {
MyCustomMarker(state)
}
title = "Magenta marker in Sydney",
pinConfig = pinConfig
)
}
```
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.

</details>

Expand Down Expand Up @@ -283,7 +289,7 @@ This library provides optional utilities in the `maps-compose-utils` library fro
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](app/src/main/java/com/google/maps/android/compose/MapClusteringActivity.kt) demonstrates usage.
The [MarkerClusteringActivity](app/src/main/java/com/google/maps/android/compose/MarkerClusteringActivity.kt) demonstrates usage.

```kotlin
Clustering(
Expand Down Expand Up @@ -364,12 +370,13 @@ Contributions are welcome and encouraged! See [contributing] for more info.

## Support

Encounter an issue while using this library?
This library is offered via an open source [license](LICENSE). It is not governed by the Google Maps Platform [Technical Support Services Guidelines](https://cloud.google.com/maps-platform/terms/tssg?utm_source=github&utm_medium=documentation&utm_campaign=&utm_content=android_oss), the [SLA](https://cloud.google.com/maps-platform/terms/sla?utm_source=github&utm_medium=documentation&utm_campaign=&utm_content=android_oss), or the [Deprecation Policy](https://cloud.google.com/maps-platform/terms?utm_source=github&utm_medium=documentation&utm_campaign=&utm_content=android_oss) (however, any Google Maps Platform services used by the library remain subject to the Google Maps Platform Terms of Service).

This library adheres to [semantic versioning](https://semver.org/) to indicate when backwards-incompatible changes are introduced.

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].
If you find a bug, or have a feature request, please [file an issue] on GitHub.

You can also discuss this library on our [Discord server].
If you would like to get answers to technical questions from other Google Maps Platform developers, ask through one of our [developer community channels](https://developers.google.com/maps/developer-community?utm_source=github&utm_medium=documentation&utm_campaign=&utm_content=android_oss) including the Google Maps Platform [Discord server].

[maps-sdk]: https://developers.google.com/maps/documentation/android-sdk
[api-key]: https://developers.google.com/maps/documentation/android-sdk/get-api-key
Expand Down
8 changes: 2 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,11 @@ dependencies {
androidTestImplementation libs.androidx.test.compose.ui
androidTestImplementation libs.coroutines

// Uncomment the implementation 'com.google...` declaration and comment out the project
// declaration if you want to test the sample app with a Maven Central release of the library.
//implementation "com.google.maps.android:maps-compose:2.2.1"
// Instead of the lines below, regular apps would load these libraries from Maven according to
// the README installation instructions
implementation project(':maps-compose')
//implementation "com.google.maps.android:maps-compose-widgets:1.0.0"
implementation project(':maps-compose-widgets')
//implementation "com.google.maps.android:maps-compose-utils:1.0.0"
implementation project(':maps-compose-utils')
implementation libs.maps.playservice
}

secrets {
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@
<activity
android:name=".BasicMapActivity"
android:exported="false" />
<activity
android:name=".AdvancedMarkersActivity"
android:exported="false"/>
<activity
android:name=".MapInColumnActivity"
android:exported="false"/>
<activity
android:name=".MapClusteringActivity"
android:name=".MarkerClusteringActivity"
android:exported="false"/>
<activity
android:name=".LocationTrackingActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.maps.android.compose


import android.R.drawable.ic_menu_myplaces
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.GoogleMapOptions
import com.google.android.gms.maps.MapsInitializer
import com.google.android.gms.maps.OnMapsSdkInitializedCallback
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.PinConfig


private const val TAG = "AdvancedMarkersActivity"

private val santiago = LatLng(-33.4489, -70.6693)
private val bogota = LatLng(-4.7110, -74.0721)
private val lima = LatLng(-12.0464, -77.0428)
private val salvador = LatLng(-12.9777, -38.5016)
private val center = LatLng(-18.000, -58.000)
private val defaultCameraPosition1 = CameraPosition.fromLatLngZoom(center, 2f)
class AdvancedMarkersActivity : ComponentActivity(), OnMapsSdkInitializedCallback {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MapsInitializer.initialize(applicationContext, MapsInitializer.Renderer.LATEST, this)
setContent {
// Observing and controlling the camera's state can be done with a CameraPositionState
val cameraPositionState = rememberCameraPositionState {
position = defaultCameraPosition1
}
val mapProperties by remember {
mutableStateOf(MapProperties(mapType = MapType.NORMAL))
}
val marker1State = rememberMarkerState(position = santiago)
val marker2State = rememberMarkerState(position = bogota)
val marker3State = rememberMarkerState(position = lima)
val marker4State = rememberMarkerState(position = salvador)

// Drawing on the map is accomplished with a child-based API
val markerClick: (Marker) -> Boolean = {
Log.d(TAG, "${it.title} was clicked")
cameraPositionState.projection?.let { projection ->
Log.d(TAG, "The current projection is: $projection")
}
false
}
Box(Modifier.fillMaxSize()) {
GoogleMap(
modifier = Modifier.matchParentSize(),
googleMapOptionsFactory = {
GoogleMapOptions().mapId("DEMO_MAP_ID")
},
cameraPositionState = cameraPositionState,
properties = mapProperties,
onPOIClick = {
Log.d(TAG, "POI clicked: ${it.name}")
}
) {

val textView = TextView(this@AdvancedMarkersActivity)
textView.text = "Hello!!"
textView.setBackgroundColor(Color.BLACK)
textView.setTextColor(Color.YELLOW)

AdvancedMarker(
state = marker4State,
onClick = markerClick,
collisionBehavior = 1,
iconView = textView,
title="Marker 4"
)

val pinConfig = PinConfig.builder()
.setBackgroundColor(Color.MAGENTA)
.setBorderColor(Color.WHITE)
.build()

AdvancedMarker(
state = marker1State,
onClick = markerClick,
collisionBehavior = 1,
pinConfig = pinConfig,
title="Marker 1"
)

val glyphOne = PinConfig.Glyph("A", Color.BLACK)
val pinConfig2 = PinConfig.builder()
.setGlyph(glyphOne)
.build()

AdvancedMarker(
state = marker2State,
onClick = markerClick,
collisionBehavior = 1,
pinConfig = pinConfig2,
title="Marker 2"
)

val glyphImage: Int = ic_menu_myplaces
val descriptor = BitmapDescriptorFactory.fromResource(glyphImage)
val pinConfig3 = PinConfig.builder()
.setGlyph(PinConfig.Glyph(descriptor))
.build()

AdvancedMarker(
state = marker3State,
onClick = markerClick,
collisionBehavior = 1,
pinConfig = pinConfig3,
title="Marker 3"
)

}
}
}
}

override fun onMapsSdkInitialized(renderer: MapsInitializer.Renderer) {
when (renderer) {
MapsInitializer.Renderer.LATEST -> Log.d("MapsDemo", "The latest version of the renderer is used.")
MapsInitializer.Renderer.LEGACY -> Log.d("MapsDemo", "The legacy version of the renderer is used.")
else -> {}
}
}
}
17 changes: 11 additions & 6 deletions app/src/main/java/com/google/maps/android/compose/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.google.maps.android.compose.theme.MapsComposeSampleTheme

private const val TAG = "MapSampleActivity"

class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -63,28 +61,35 @@ class MainActivity : ComponentActivity() {
Text(getString(R.string.basic_map_activity))
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
onClick = {
context.startActivity(Intent(context, AdvancedMarkersActivity::class.java))
}) {
Text(getString(R.string.advanced_markers))
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
onClick = {
context.startActivity(
Intent(
context,
MapInColumnActivity::class.java
MarkerClusteringActivity::class.java
)
)
}) {
Text(getString(R.string.map_in_column_activity))
Text(getString(R.string.marker_clustering_activity))
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
onClick = {
context.startActivity(
Intent(
context,
MapClusteringActivity::class.java
MapInColumnActivity::class.java
)
)
}) {
Text(getString(R.string.map_clustering_activity))
Text(getString(R.string.map_in_column_activity))
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import com.google.maps.android.clustering.ClusterItem
import com.google.maps.android.compose.clustering.Clustering
import kotlin.random.Random

private val TAG = MapClusteringActivity::class.simpleName
private val TAG = MarkerClusteringActivity::class.simpleName

class MapClusteringActivity : ComponentActivity() {
class MarkerClusteringActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Expand Down Expand Up @@ -60,7 +60,7 @@ fun GoogleMapClustering(items: List<MyItem>) {
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(singapore, 10f)
position = CameraPosition.fromLatLngZoom(singapore, 6f)
}
) {
Clustering(
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
<string name="app_name">android-maps-compose</string>
<string name="main_activity_title">"Maps Compose Demos \uD83D\uDDFA"</string>
<string name="basic_map_activity">Basic Map</string>
<string name="advanced_markers">Advanced Markers</string>
<string name="map_in_column_activity">Map In Column</string>
<string name="map_clustering_activity">Map Clustering</string>
<string name="marker_clustering_activity">Marker Clustering</string>
<string name="location_tracking_activity">Location Tracking</string>
<string name="scale_bar_activity">Scale Bar</string>
<string name="street_view">Street View</string>
Expand Down
3 changes: 1 addition & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ junitktx = "1.1.5"
junit = "4.13.2"
kotlin = "1.9.10"
material = "1.9.0"
mapsktx = "4.0.0"
mapsktx = "5.0.0"
mapsecrets = "2.0.1"

[libraries]
Expand All @@ -39,7 +39,6 @@ kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "ko
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
maps-ktx-std = { module = "com.google.maps.android:maps-ktx", version.ref = "mapsktx" }
maps-ktx-utils = { module = "com.google.maps.android:maps-utils-ktx", version.ref = "mapsktx" }
maps-playservice = { module = "com.google.android.gms:play-services-maps", version.require = "18.1.0" }
maps-secrets-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "mapsecrets" }
material = { module = "com.google.android.material:material", version.ref = "material" }
test-junit = { module = "junit:junit", version.ref = "junit" }
Expand Down
2 changes: 0 additions & 2 deletions maps-compose-utils/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,5 @@ dependencies {
implementation platform(libs.androidx.compose.bom)
implementation libs.androidx.compose.ui
implementation libs.kotlin
implementation libs.maps.playservice
implementation libs.maps.ktx.std
api libs.maps.ktx.utils
}
1 change: 0 additions & 1 deletion maps-compose-widgets/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ dependencies {
implementation libs.androidx.compose.material
implementation libs.androidx.core
implementation libs.kotlin
implementation libs.maps.playservice
implementation libs.maps.ktx.std
implementation libs.maps.ktx.utils

Expand Down
1 change: 0 additions & 1 deletion maps-compose/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ dependencies {
implementation libs.androidx.core
implementation libs.androidx.compose.foundation
implementation libs.kotlin
implementation libs.maps.playservice
implementation libs.maps.ktx.std

testImplementation libs.test.junit
Expand Down

0 comments on commit d949465

Please sign in to comment.