diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8e938ca4..69d8deea 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -57,6 +57,9 @@ + diff --git a/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt b/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt index 0fd27819..78be4448 100644 --- a/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// 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. diff --git a/app/src/main/java/com/google/maps/android/compose/CustomControlsActivity.kt b/app/src/main/java/com/google/maps/android/compose/CustomControlsActivity.kt new file mode 100644 index 00000000..1efae7d7 --- /dev/null +++ b/app/src/main/java/com/google/maps/android/compose/CustomControlsActivity.kt @@ -0,0 +1,109 @@ +// 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.os.Bundle +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +class CustomControlsActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + var isMapLoaded by remember { mutableStateOf(false) } + val mapProperties by remember { mutableStateOf(MapProperties(isMyLocationEnabled = true)) } + // Observing and controlling the camera's state can be done with a CameraPositionState + val cameraPositionState = rememberCameraPositionState { + position = defaultCameraPosition + } + + Box(Modifier.fillMaxSize()) { + GoogleMap( + modifier = Modifier.matchParentSize(), + cameraPositionState = cameraPositionState, + onMapLoaded = { + isMapLoaded = true + }, + + myLocationButton = { + MapButton( + "This is a custom location button", + onClick = { + Toast.makeText( + this@CustomControlsActivity, + "Click on my location", + Toast.LENGTH_SHORT + ).show() + }) + }) + + if (!isMapLoaded) { + AnimatedVisibility( + modifier = Modifier + .matchParentSize(), + visible = !isMapLoaded, + enter = EnterTransition.None, + exit = fadeOut() + ) { + CircularProgressIndicator( + modifier = Modifier + .background(MaterialTheme.colors.background) + .wrapContentSize() + ) + } + } + } + } + } + + @Composable + private fun MapButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier) { + Button( + modifier = modifier.padding(4.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = MaterialTheme.colors.onPrimary, + contentColor = MaterialTheme.colors.primary + ), + onClick = onClick + ) { + Text(text = text, style = MaterialTheme.typography.body1) + } + } + + +} diff --git a/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt b/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt index 86462124..3eed60a0 100644 --- a/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt @@ -1,3 +1,18 @@ +// 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.location.Location @@ -100,6 +115,9 @@ class LocationTrackingActivity : AppCompatActivity() { onMapLoaded = { isMapLoaded = true }, + // This listener overrides the behavior for the location button. It is intended to be used when a + // custom behavior is needed. + onMyLocationButtonClick = { Log.d(TAG,"Overriding the onMyLocationButtonClick with this Log"); true }, locationSource = locationSource, properties = mapProperties ) 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 b452868a..ff8e0bdc 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 @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// 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. @@ -112,6 +112,13 @@ class MainActivity : ComponentActivity() { }) { Text(getString(R.string.street_view)) } + Spacer(modifier = Modifier.padding(5.dp)) + Button( + onClick = { + context.startActivity(Intent(context, CustomControlsActivity::class.java)) + }) { + Text(getString(R.string.custom_location_button)) + } } } } diff --git a/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt b/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt index e7d4d6be..d344318e 100644 --- a/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/StreetViewActivity.kt @@ -1,3 +1,17 @@ +// 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.os.Bundle @@ -12,12 +26,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.material.Button import androidx.compose.material.Switch import androidx.compose.material.Text -import androidx.compose.material.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -28,7 +38,6 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.unit.dp import com.google.android.gms.maps.StreetViewPanoramaOptions import com.google.maps.android.compose.streetview.StreetView diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5e7a0bc2..dd10f260 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,4 +23,5 @@ Location Tracking Scale Bar Street View + Custom Location Button \ No newline at end of file diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt b/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt index dff08bb0..da27b122 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt @@ -20,6 +20,7 @@ import android.location.Location import android.os.Bundle import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.runtime.Composable import androidx.compose.runtime.Composition import androidx.compose.runtime.CompositionContext @@ -87,6 +88,7 @@ public fun GoogleMap( onMyLocationClick: ((Location) -> Unit)? = null, onPOIClick: ((PointOfInterest) -> Unit)? = null, contentPadding: PaddingValues = NoPadding, + myLocationButton: (@Composable @GoogleMapComposable () -> Unit)? = null, content: (@Composable @GoogleMapComposable () -> Unit)? = null, ) { // When in preview, early return a Box with the received modifier preserving layout @@ -115,11 +117,18 @@ public fun GoogleMap( val currentLocationSource by rememberUpdatedState(locationSource) val currentCameraPositionState by rememberUpdatedState(cameraPositionState) val currentContentPadding by rememberUpdatedState(contentPadding) - val currentUiSettings by rememberUpdatedState(uiSettings) + + // If we pass a custom location button, the native one is deactivated. + val currentUiSettings by rememberUpdatedState(if (myLocationButton != null) { + uiSettings.copy(myLocationButtonEnabled = false) + } else { + uiSettings + }) val currentMapProperties by rememberUpdatedState(properties) val parentComposition = rememberCompositionContext() val currentContent by rememberUpdatedState(content) + val currentLocation by rememberUpdatedState(myLocationButton) LaunchedEffect(Unit) { disposingComposition { @@ -141,6 +150,10 @@ public fun GoogleMap( } } } + Row(modifier = modifier) { + currentLocation?.invoke() + } + } internal suspend inline fun disposingComposition(factory: () -> Composition) { diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt b/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt index a09af9cc..15b5a124 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// 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. diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt b/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt index 634591b0..34d63b74 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// 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. @@ -75,12 +75,14 @@ internal class MapPropertiesNode( map.setOnCameraMoveListener { cameraPositionState.rawPosition = map.cameraPosition } + map.setOnMapClickListener(clickListeners.onMapClick) map.setOnMapLongClickListener(clickListeners.onMapLongClick) map.setOnMapLoadedCallback(clickListeners.onMapLoaded) - map.setOnMyLocationButtonClickListener(clickListeners.onMyLocationButtonClick) + map.setOnMyLocationButtonClickListener { clickListeners.onMyLocationButtonClick?.invoke() == true } map.setOnMyLocationClickListener(clickListeners.onMyLocationClick) map.setOnPoiClickListener(clickListeners.onPOIClick) + map.setOnIndoorStateChangeListener(object : GoogleMap.OnIndoorStateChangeListener { override fun onIndoorBuildingFocused() { clickListeners.indoorStateChangeListener.onIndoorBuildingFocused()