From 6e2cde7026c16beed9c662573911795eea83bba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20L=C3=B3pez-Manas?= Date: Fri, 20 Oct 2023 11:54:32 +0200 Subject: [PATCH 1/4] feat: added support for Advanced Markers --- app/src/main/AndroidManifest.xml | 3 + .../compose/AdvancedMarkersActivity.kt | 142 ++++++++++++ .../maps/android/compose/MainActivity.kt | 9 +- app/src/main/res/values/strings.xml | 2 + gradle/libs.versions.toml | 2 +- .../com/google/maps/android/compose/Marker.kt | 206 ++++++++++++++++++ 6 files changed, 361 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 69d8deea0..c8841b5bd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -60,6 +60,9 @@ + diff --git a/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt b/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt new file mode 100644 index 000000000..1c4823854 --- /dev/null +++ b/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt @@ -0,0 +1,142 @@ +// 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 +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.Marker +import com.google.android.gms.maps.model.PinConfig + + +private const val TAG = "AdvancedMarkersActivity" + +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 = defaultCameraPosition + } + val mapProperties by remember { + mutableStateOf(MapProperties(mapType = MapType.NORMAL)) + } + val singaporeState = rememberMarkerState(position = singapore) + val singapore2State = rememberMarkerState(position = singapore2) + val singapore3State = rememberMarkerState(position = singapore3) + val singapore4State = rememberMarkerState(position = singapore4) + + // 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("45a7dec634a854b0") + }, + 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 = singapore3State, + onClick = markerClick, + collisionBehavior = 1, + iconView = textView + ) + + val pinConfigBuilder = PinConfig.builder() + pinConfigBuilder.setBackgroundColor(Color.MAGENTA) + pinConfigBuilder.setBorderColor(resources.getColor(R.color.holo_orange_dark)) + + val pinConfig = pinConfigBuilder.build() + + AdvancedMarker( + state = singapore2State, + onClick = markerClick, + collisionBehavior = 1, + pinConfig = pinConfig + ) + val pinConfigBuilder2 = PinConfig.builder() + val glyphOne = PinConfig.Glyph("A", resources.getColor(R.color.black)) + pinConfigBuilder2.setGlyph(glyphOne) + + val pinConfig2 = pinConfigBuilder2.build() + + AdvancedMarker( + state = singaporeState, + onClick = markerClick, + collisionBehavior = 1, + pinConfig = pinConfig2 + ) + + val pinConfigBuilder3 = PinConfig.builder() + val glyphImage: Int = R.drawable.ic_menu_report_image + val descriptor = BitmapDescriptorFactory.fromResource(glyphImage) + pinConfigBuilder3.setGlyph(PinConfig.Glyph(descriptor)) + val pinConfig3 = pinConfigBuilder3.build() + + AdvancedMarker( + state = singapore4State, + onClick = markerClick, + collisionBehavior = 1, + pinConfig = pinConfig3 + ) + + } + } + } + } + + 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 -> {} + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/google/maps/android/compose/MainActivity.kt b/app/src/main/java/com/google/maps/android/compose/MainActivity.kt index ff8e0bdc7..e67d1cad9 100644 --- a/app/src/main/java/com/google/maps/android/compose/MainActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/MainActivity.kt @@ -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?) { @@ -119,6 +117,13 @@ class MainActivity : ComponentActivity() { }) { Text(getString(R.string.custom_location_button)) } + Spacer(modifier = Modifier.padding(5.dp)) + Button( + onClick = { + context.startActivity(Intent(context, AdvancedMarkersActivity::class.java)) + }) { + Text(getString(R.string.advanced_markers)) + } } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dd10f260d..76b26a7a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,5 +23,7 @@ Location Tracking Scale Bar Street View + Custom Location Button + Advanced Markers \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 80f803570..2232406db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ 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-playservice = { module = "com.google.android.gms:play-services-maps", version.require = "18.2.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" } diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt index 5412e917b..eff2e37e9 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt @@ -14,6 +14,7 @@ package com.google.maps.android.compose +import android.view.View import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode import androidx.compose.runtime.CompositionContext @@ -27,9 +28,12 @@ import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.geometry.Offset +import com.google.android.gms.maps.model.AdvancedMarkerOptions import com.google.android.gms.maps.model.BitmapDescriptor +import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.Marker +import com.google.android.gms.maps.model.PinConfig import com.google.maps.android.ktx.addMarker internal class MarkerNode( @@ -46,6 +50,7 @@ internal class MarkerNode( override fun onAttached() { markerState.marker = marker } + override fun onRemoved() { markerState.marker = null marker.remove() @@ -514,3 +519,204 @@ private fun MarkerImpl( } ) } + + +/** + * A composable for an advanced marker on the map. + * + * @param state the [MarkerState] to be used to control or observe the marker + * state such as its position and info window + * @param alpha the alpha (opacity) of the marker + * @param anchor the anchor for the marker image + * @param draggable sets the draggability for the marker + * @param flat sets if the marker should be flat against the map + * @param infoWindowAnchor the anchor point of the info window on the marker image + * @param rotation the rotation of the marker in degrees clockwise about the marker's anchor point + * @param snippet the snippet for the marker + * @param tag optional tag to associate with the marker + * @param title the title for the marker + * @param visible the visibility of the marker + * @param zIndex the z-index of the marker + * @param onClick a lambda invoked when the marker is clicked + * @param onInfoWindowClick a lambda invoked when the marker's info window is clicked + * @param onInfoWindowClose a lambda invoked when the marker's info window is closed + * @param onInfoWindowLongClick a lambda invoked when the marker's info window is long clicked + * @param pinConfig the PinConfig object that will be used for the advanced marker + * @param iconView the custom view to be used on the advanced marker + * @param collisionBehavior the expected collision behavior + */ +@Composable +@GoogleMapComposable +public fun AdvancedMarker( + state: MarkerState = rememberMarkerState(), + alpha: Float = 1.0f, + anchor: Offset = Offset(0.5f, 1.0f), + draggable: Boolean = false, + flat: Boolean = false, + infoWindowAnchor: Offset = Offset(0.5f, 0.0f), + rotation: Float = 0.0f, + snippet: String? = null, + tag: Any? = null, + title: String? = null, + visible: Boolean = true, + zIndex: Float = 0.0f, + onClick: (Marker) -> Boolean = { false }, + onInfoWindowClick: (Marker) -> Unit = {}, + onInfoWindowClose: (Marker) -> Unit = {}, + onInfoWindowLongClick: (Marker) -> Unit = {}, + pinConfig: PinConfig? = null, + iconView: View? = null, + collisionBehavior: Int = AdvancedMarkerOptions.CollisionBehavior.REQUIRED +) { + + AdvancedMarkerImpl( + state = state, + alpha = alpha, + anchor = anchor, + draggable = draggable, + flat = flat, + infoWindowAnchor = infoWindowAnchor, + rotation = rotation, + snippet = snippet, + tag = tag, + title = title, + visible = visible, + zIndex = zIndex, + onClick = onClick, + onInfoWindowClick = onInfoWindowClick, + onInfoWindowClose = onInfoWindowClose, + onInfoWindowLongClick = onInfoWindowLongClick, + pinConfig = pinConfig, + iconView = iconView, + collisionBehavior = collisionBehavior + ) +} + +/** + * Internal implementation for an advanced marker on a Google map. + * + * @param state the [MarkerState] to be used to control or observe the marker + * state such as its position and info window + * @param alpha the alpha (opacity) of the marker + * @param anchor the anchor for the marker image + * @param draggable sets the draggability for the marker + * @param flat sets if the marker should be flat against the map + * @param infoWindowAnchor the anchor point of the info window on the marker image + * @param rotation the rotation of the marker in degrees clockwise about the marker's anchor point + * @param snippet the snippet for the marker + * @param tag optional tag to associate with the marker + * @param title the title for the marker + * @param visible the visibility of the marker + * @param zIndex the z-index of the marker + * @param onClick a lambda invoked when the marker is clicked + * @param onInfoWindowClick a lambda invoked when the marker's info window is clicked + * @param onInfoWindowClose a lambda invoked when the marker's info window is closed + * @param onInfoWindowLongClick a lambda invoked when the marker's info window is long clicked + * @param infoWindow optional composable lambda expression for customizing + * the entire info window. If this value is non-null, the value in infoContent] + * will be ignored. + * @param infoContent optional composable lambda expression for customizing + * the info window's content. If this value is non-null, [infoWindow] must be null. + * @param pinConfig the PinConfig object that will be used for the advanced marker + * @param iconView the custom view to be used on the advanced marker + * @param collisionBehavior the expected collision behavior + */ +@Composable +@GoogleMapComposable +private fun AdvancedMarkerImpl( + + state: MarkerState = rememberMarkerState(), + alpha: Float = 1.0f, + anchor: Offset = Offset(0.5f, 1.0f), + draggable: Boolean = false, + flat: Boolean = false, + infoWindowAnchor: Offset = Offset(0.5f, 0.0f), + rotation: Float = 0.0f, + snippet: String? = null, + tag: Any? = null, + title: String? = null, + visible: Boolean = true, + zIndex: Float = 0.0f, + onClick: (Marker) -> Boolean = { false }, + onInfoWindowClick: (Marker) -> Unit = {}, + onInfoWindowClose: (Marker) -> Unit = {}, + onInfoWindowLongClick: (Marker) -> Unit = {}, + infoWindow: (@Composable (Marker) -> Unit)? = null, + infoContent: (@Composable (Marker) -> Unit)? = null, + pinConfig: PinConfig? = null, + iconView: View? = null, + collisionBehavior: Int = AdvancedMarkerOptions.CollisionBehavior.REQUIRED +) { + + val mapApplier = currentComposer.applier as? MapApplier + val compositionContext = rememberCompositionContext() + + val advancedMarkerOptions = AdvancedMarkerOptions() + .position(state.position) + .collisionBehavior(collisionBehavior) + if (iconView != null) { + advancedMarkerOptions.iconView(iconView) + } else if (pinConfig != null) { + advancedMarkerOptions.icon(BitmapDescriptorFactory.fromPinConfig(pinConfig)) + } + + ComposeNode( + factory = { + val marker = mapApplier?.map?.addMarker(advancedMarkerOptions) + ?: error("Error adding marker") + marker.tag = tag + MarkerNode( + compositionContext = compositionContext, + marker = marker, + markerState = state, + onMarkerClick = onClick, + onInfoWindowClick = onInfoWindowClick, + onInfoWindowClose = onInfoWindowClose, + onInfoWindowLongClick = onInfoWindowLongClick, + infoContent = infoContent, + infoWindow = infoWindow, + ) + }, + update = { + update(onClick) { this.onMarkerClick = it } + update(onInfoWindowClick) { this.onInfoWindowClick = it } + update(onInfoWindowClose) { this.onInfoWindowClose = it } + update(onInfoWindowLongClick) { this.onInfoWindowLongClick = it } + update(infoContent) { this.infoContent = it } + update(infoWindow) { this.infoWindow = it } + + set(alpha) { this.marker.alpha = it } + set(anchor) { this.marker.setAnchor(it.x, it.y) } + set(draggable) { this.marker.isDraggable = it } + set(flat) { this.marker.isFlat = it } + set(infoWindowAnchor) { this.marker.setInfoWindowAnchor(it.x, it.y) } + set(state.position) { this.marker.position = it } + set(rotation) { this.marker.rotation = it } + set(snippet) { + this.marker.snippet = it + if (this.marker.isInfoWindowShown) { + this.marker.showInfoWindow() + } + } + set(tag) { this.marker.tag = it } + set(title) { + this.marker.title = it + if (this.marker.isInfoWindowShown) { + this.marker.showInfoWindow() + } + } + set(pinConfig) { + if (iconView == null) { + this.marker.setIcon(pinConfig?.let { it1 -> + BitmapDescriptorFactory.fromPinConfig( + it1 + ) + }) + } + } + + set(visible) { this.marker.isVisible = it } + set(zIndex) { this.marker.zIndex = it } + } + ) +} From 2b438b3e71faa748560f4d628297df47b2d6b3d6 Mon Sep 17 00:00:00 2001 From: Angela Yu <5506675+wangela@users.noreply.github.com> Date: Fri, 27 Oct 2023 17:39:38 -0700 Subject: [PATCH 2/4] refactor: sample activity titles and migrate README to advanced markers --- README.md | 29 +++++--- app/src/main/AndroidManifest.xml | 8 +-- .../compose/AdvancedMarkersActivity.kt | 67 +++++++++++-------- .../maps/android/compose/MainActivity.kt | 22 +++--- ...ctivity.kt => MarkerClusteringActivity.kt} | 6 +- app/src/main/res/values/strings.xml | 5 +- 6 files changed, 78 insertions(+), 59 deletions(-) rename app/src/main/java/com/google/maps/android/compose/{MapClusteringActivity.kt => MarkerClusteringActivity.kt} (97%) diff --git a/README.md b/README.md index e31848ce6..3c74da65a 100644 --- a/README.md +++ b/README.md @@ -158,33 +158,42 @@ 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 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c8841b5bd..c7ea8c0db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,11 +42,14 @@ + - diff --git a/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt b/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt index 1c4823854..48cf92e84 100644 --- a/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/AdvancedMarkersActivity.kt @@ -15,7 +15,7 @@ package com.google.maps.android.compose -import android.R +import android.R.drawable.ic_menu_myplaces import android.graphics.Color import android.os.Bundle import android.util.Log @@ -32,12 +32,20 @@ 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?) { @@ -46,15 +54,15 @@ class AdvancedMarkersActivity : ComponentActivity(), OnMapsSdkInitializedCallbac setContent { // Observing and controlling the camera's state can be done with a CameraPositionState val cameraPositionState = rememberCameraPositionState { - position = defaultCameraPosition + position = defaultCameraPosition1 } val mapProperties by remember { mutableStateOf(MapProperties(mapType = MapType.NORMAL)) } - val singaporeState = rememberMarkerState(position = singapore) - val singapore2State = rememberMarkerState(position = singapore2) - val singapore3State = rememberMarkerState(position = singapore3) - val singapore4State = rememberMarkerState(position = singapore4) + 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 = { @@ -68,7 +76,7 @@ class AdvancedMarkersActivity : ComponentActivity(), OnMapsSdkInitializedCallbac GoogleMap( modifier = Modifier.matchParentSize(), googleMapOptionsFactory = { - GoogleMapOptions().mapId("45a7dec634a854b0") + GoogleMapOptions().mapId("DEMO_MAP_ID") }, cameraPositionState = cameraPositionState, properties = mapProperties, @@ -83,48 +91,51 @@ class AdvancedMarkersActivity : ComponentActivity(), OnMapsSdkInitializedCallbac textView.setTextColor(Color.YELLOW) AdvancedMarker( - state = singapore3State, + state = marker4State, onClick = markerClick, collisionBehavior = 1, - iconView = textView + iconView = textView, + title="Marker 4" ) - val pinConfigBuilder = PinConfig.builder() - pinConfigBuilder.setBackgroundColor(Color.MAGENTA) - pinConfigBuilder.setBorderColor(resources.getColor(R.color.holo_orange_dark)) - - val pinConfig = pinConfigBuilder.build() + val pinConfig = PinConfig.builder() + .setBackgroundColor(Color.MAGENTA) + .setBorderColor(Color.WHITE) + .build() AdvancedMarker( - state = singapore2State, + state = marker1State, onClick = markerClick, collisionBehavior = 1, - pinConfig = pinConfig + pinConfig = pinConfig, + title="Marker 1" ) - val pinConfigBuilder2 = PinConfig.builder() - val glyphOne = PinConfig.Glyph("A", resources.getColor(R.color.black)) - pinConfigBuilder2.setGlyph(glyphOne) - val pinConfig2 = pinConfigBuilder2.build() + val glyphOne = PinConfig.Glyph("A", Color.BLACK) + val pinConfig2 = PinConfig.builder() + .setGlyph(glyphOne) + .build() AdvancedMarker( - state = singaporeState, + state = marker2State, onClick = markerClick, collisionBehavior = 1, - pinConfig = pinConfig2 + pinConfig = pinConfig2, + title="Marker 2" ) - val pinConfigBuilder3 = PinConfig.builder() - val glyphImage: Int = R.drawable.ic_menu_report_image + val glyphImage: Int = ic_menu_myplaces val descriptor = BitmapDescriptorFactory.fromResource(glyphImage) - pinConfigBuilder3.setGlyph(PinConfig.Glyph(descriptor)) - val pinConfig3 = pinConfigBuilder3.build() + val pinConfig3 = PinConfig.builder() + .setGlyph(PinConfig.Glyph(descriptor)) + .build() AdvancedMarker( - state = singapore4State, + state = marker3State, onClick = markerClick, collisionBehavior = 1, - pinConfig = pinConfig3 + pinConfig = pinConfig3, + title="Marker 3" ) } diff --git a/app/src/main/java/com/google/maps/android/compose/MainActivity.kt b/app/src/main/java/com/google/maps/android/compose/MainActivity.kt index e67d1cad9..f6f8ada02 100644 --- a/app/src/main/java/com/google/maps/android/compose/MainActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/MainActivity.kt @@ -61,16 +61,23 @@ 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( @@ -78,11 +85,11 @@ class MainActivity : ComponentActivity() { 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( @@ -117,13 +124,6 @@ class MainActivity : ComponentActivity() { }) { Text(getString(R.string.custom_location_button)) } - Spacer(modifier = Modifier.padding(5.dp)) - Button( - onClick = { - context.startActivity(Intent(context, AdvancedMarkersActivity::class.java)) - }) { - Text(getString(R.string.advanced_markers)) - } } } } diff --git a/app/src/main/java/com/google/maps/android/compose/MapClusteringActivity.kt b/app/src/main/java/com/google/maps/android/compose/MarkerClusteringActivity.kt similarity index 97% rename from app/src/main/java/com/google/maps/android/compose/MapClusteringActivity.kt rename to app/src/main/java/com/google/maps/android/compose/MarkerClusteringActivity.kt index d545dd8ee..328076c5b 100644 --- a/app/src/main/java/com/google/maps/android/compose/MapClusteringActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/MarkerClusteringActivity.kt @@ -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 { @@ -60,7 +60,7 @@ fun GoogleMapClustering(items: List) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = rememberCameraPositionState { - position = CameraPosition.fromLatLngZoom(singapore, 10f) + position = CameraPosition.fromLatLngZoom(singapore, 6f) } ) { Clustering( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 76b26a7a8..a74afdd8e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,12 +18,11 @@ android-maps-compose "Maps Compose Demos \uD83D\uDDFA" Basic Map + Advanced Markers Map In Column - Map Clustering + Marker Clustering Location Tracking Scale Bar Street View - Custom Location Button - Advanced Markers \ No newline at end of file From f77cdcfd2b85dcd588cf24da7f47a9321c53a3cc Mon Sep 17 00:00:00 2001 From: Angela Yu <5506675+wangela@users.noreply.github.com> Date: Fri, 27 Oct 2023 18:34:31 -0700 Subject: [PATCH 3/4] docs: update README --- README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3c74da65a..63cfaf9b0 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ You no longer need to specify the Maps SDK for Android or its Utility Library as ```groovy dependencies { implementation 'com.google.maps.android:maps-compose:3.1.1' - + // Optionally, you can include the Compose utils library for Clustering, etc. implementation 'com.google.maps.android:maps-compose-utils:3.1.1' @@ -188,7 +188,7 @@ GoogleMap( val pinConfig = PinConfig.builder() .setBackgroundColor(Color.MAGENTA) .build() - + AdvancedMarker( state = MarkerState(position = LatLng(-34, 151)), title = "Magenta marker in Sydney", @@ -196,9 +196,6 @@ GoogleMap( ) } ``` -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. @@ -282,7 +279,7 @@ This library also provides optional utilities in the `maps-compose-utils` librar 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( @@ -313,8 +310,8 @@ The [ScaleBarActivity](app/src/main/java/com/google/maps/android/compose/ScaleBa Both versions of this widget leverage the `CameraPositionState` in `maps-compose` and therefore are very simple to configure with their defaults: ```kotlin -Box(Modifier.fillMaxSize()) { - +Box(Modifier.fillMaxSize()) { + GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState @@ -337,7 +334,7 @@ Box(Modifier.fillMaxSize()) { .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. @@ -348,12 +345,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 From cd73e39e2b985fbddada60519bb8edc737208a42 Mon Sep 17 00:00:00 2001 From: Angela Yu <5506675+wangela@users.noreply.github.com> Date: Fri, 27 Oct 2023 18:43:04 -0700 Subject: [PATCH 4/4] chore: clean up dependencies, update to maps-ktx 5.0.0 --- app/build.gradle | 8 ++------ gradle/libs.versions.toml | 3 +-- maps-compose-utils/build.gradle | 2 -- maps-compose-widgets/build.gradle | 1 - maps-compose/build.gradle | 1 - 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c823a2ee2..8701f609f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2232406db..c8a074d53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -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] @@ -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.2.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" } diff --git a/maps-compose-utils/build.gradle b/maps-compose-utils/build.gradle index 2febaa60e..c5ae7898b 100644 --- a/maps-compose-utils/build.gradle +++ b/maps-compose-utils/build.gradle @@ -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 } diff --git a/maps-compose-widgets/build.gradle b/maps-compose-widgets/build.gradle index ecd945fc8..ca0187bfd 100644 --- a/maps-compose-widgets/build.gradle +++ b/maps-compose-widgets/build.gradle @@ -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 diff --git a/maps-compose/build.gradle b/maps-compose/build.gradle index 5da3074a3..ce89fd508 100644 --- a/maps-compose/build.gradle +++ b/maps-compose/build.gradle @@ -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