From 6ca7fc5b2a74b9bb37510fea6bd2c288b8663f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Wed, 1 Nov 2023 18:55:22 +0100 Subject: [PATCH] feat: added support for mergeDescendants --- app/src/main/AndroidManifest.xml | 3 + .../android/compose/AccessibilityActivity.kt | 79 +++++++++++++++++++ .../maps/android/compose/BasicMapActivity.kt | 8 +- .../maps/android/compose/MainActivity.kt | 7 ++ app/src/main/res/values/strings.xml | 1 + .../google/maps/android/compose/GoogleMap.kt | 4 +- .../google/maps/android/compose/MapUpdater.kt | 6 ++ .../com/google/maps/android/compose/Marker.kt | 4 + 8 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/google/maps/android/compose/AccessibilityActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c7ea8c0db..1778fa5d2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,6 +63,9 @@ + diff --git a/app/src/main/java/com/google/maps/android/compose/AccessibilityActivity.kt b/app/src/main/java/com/google/maps/android/compose/AccessibilityActivity.kt new file mode 100644 index 000000000..1b52b1496 --- /dev/null +++ b/app/src/main/java/com/google/maps/android/compose/AccessibilityActivity.kt @@ -0,0 +1,79 @@ +// 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.util.Log +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.model.Marker + +private const val TAG = "AccessibilityActivity" + + +class AccessibilityActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + val singaporeState = rememberMarkerState(position = singapore) + val cameraPositionState = rememberCameraPositionState { + position = defaultCameraPosition + } + val uiSettings by remember { mutableStateOf(MapUiSettings(compassEnabled = false)) } + val mapProperties by remember { + mutableStateOf(MapProperties(mapType = MapType.NORMAL)) + } + + Box(Modifier.fillMaxSize()) { + GoogleMap( + // mergeDescendants will remove accessibility from the entire map and content inside. + mergeDescendants = true, + // alternatively, contentDescription will deactivate it for the maps, but not markers. + contentDescription = "", + cameraPositionState = cameraPositionState, + properties = mapProperties, + uiSettings = uiSettings, + onPOIClick = { + Log.d(TAG, "POI clicked: ${it.name}") + } + ) { + val markerClick: (Marker) -> Boolean = { + Log.d(TAG, "${it.title} was clicked") + cameraPositionState.projection?.let { projection -> + Log.d(TAG, "The current projection is: $projection") + } + false + } + + Marker( + // contentDescription overrides title for TalkBack + contentDescription = "Description of the marker", + state = singaporeState, + title = "Marker in Singapore", + onClick = markerClick + ) + } + } + } + } +} + 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 5aae2cf9a..40d40c1b8 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 @@ -44,6 +44,7 @@ import androidx.compose.material.Switch import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -53,8 +54,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag -import androidx.compose.ui.semantics.clearAndSetSemantics -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -129,7 +128,7 @@ fun GoogleMapView( var uiSettings by remember { mutableStateOf(MapUiSettings(compassEnabled = false)) } var shouldAnimateZoom by remember { mutableStateOf(true) } - var ticker by remember { mutableStateOf(0) } + var ticker by remember { mutableIntStateOf(0) } var mapProperties by remember { mutableStateOf(MapProperties(mapType = MapType.NORMAL)) } @@ -137,9 +136,6 @@ fun GoogleMapView( if (mapVisible) { GoogleMap( - modifier = Modifier - .semantics(mergeDescendants = true) { } - .clearAndSetSemantics { }, cameraPositionState = cameraPositionState, properties = mapProperties, uiSettings = uiSettings, 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 0b5037dbc..c9af31a19 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 @@ -127,6 +127,13 @@ class MainActivity : ComponentActivity() { }) { Text(getString(R.string.custom_location_button)) } + Spacer(modifier = Modifier.padding(5.dp)) + Button( + onClick = { + context.startActivity(Intent(context, AccessibilityActivity::class.java)) + }) { + Text(getString(R.string.accessibility_button)) + } } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a74afdd8e..378263a64 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,4 +25,5 @@ Scale Bar Street View Custom Location Button + Accessibility \ 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 5f5edc128..6b9761ec9 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 @@ -36,6 +36,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver @@ -72,6 +73,7 @@ import kotlinx.coroutines.awaitCancellation */ @Composable public fun GoogleMap( + mergeDescendants: Boolean = false, modifier: Modifier = Modifier, cameraPositionState: CameraPositionState = rememberCameraPositionState(), contentDescription: String? = null, @@ -120,11 +122,11 @@ public fun GoogleMap( val parentComposition = rememberCompositionContext() val currentContent by rememberUpdatedState(content) - LaunchedEffect(Unit) { disposingComposition { mapView.newComposition(parentComposition) { MapUpdater( + mergeDescendants = mergeDescendants, contentDescription = contentDescription, cameraPositionState = currentCameraPositionState, clickListeners = mapClickListeners, 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 34d63b745..f7ea02570 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 @@ -15,6 +15,7 @@ package com.google.maps.android.compose import android.annotation.SuppressLint +import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.runtime.ComposeNode @@ -112,6 +113,7 @@ internal val NoPadding = PaddingValues() @Suppress("NOTHING_TO_INLINE") @Composable internal inline fun MapUpdater( + mergeDescendants: Boolean = false, contentDescription: String?, cameraPositionState: CameraPositionState, clickListeners: MapClickListeners, @@ -121,6 +123,10 @@ internal inline fun MapUpdater( mapUiSettings: MapUiSettings, ) { val map = (currentComposer.applier as MapApplier).map + val mapView = (currentComposer.applier as MapApplier).mapView + if (mergeDescendants) { + mapView.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS + } val density = LocalDensity.current val layoutDirection = LocalLayoutDirection.current ComposeNode( 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 eff2e37e9..c987b7497 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 @@ -156,6 +156,7 @@ public fun rememberMarkerState( @Composable @GoogleMapComposable public fun Marker( + contentDescription: String? = "", state: MarkerState = rememberMarkerState(), alpha: Float = 1.0f, anchor: Offset = Offset(0.5f, 1.0f), @@ -175,6 +176,7 @@ public fun Marker( onInfoWindowLongClick: (Marker) -> Unit = {}, ) { MarkerImpl( + contentDescription = contentDescription, state = state, alpha = alpha, anchor = anchor, @@ -434,6 +436,7 @@ public fun MarkerInfoWindowContent( @Composable @GoogleMapComposable private fun MarkerImpl( + contentDescription: String? = "", state: MarkerState = rememberMarkerState(), alpha: Float = 1.0f, anchor: Offset = Offset(0.5f, 1.0f), @@ -459,6 +462,7 @@ private fun MarkerImpl( ComposeNode( factory = { val marker = mapApplier?.map?.addMarker { + contentDescription(contentDescription) alpha(alpha) anchor(anchor.x, anchor.y) draggable(draggable)