From 233d6ce988f7c3b35d20bf9c528a463f47ec8a71 Mon Sep 17 00:00:00 2001 From: Jonas Kalderstam Date: Thu, 14 Mar 2024 17:39:26 +0100 Subject: [PATCH] Fixed talkback for delete dialog --- .../ui/compose/deletefeed/DeleteFeedScreen.kt | 116 +++++++++++------- 1 file changed, 73 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/nononsenseapps/feeder/ui/compose/deletefeed/DeleteFeedScreen.kt b/app/src/main/java/com/nononsenseapps/feeder/ui/compose/deletefeed/DeleteFeedScreen.kt index 6c6f5a64a..395def6d0 100644 --- a/app/src/main/java/com/nononsenseapps/feeder/ui/compose/deletefeed/DeleteFeedScreen.kt +++ b/app/src/main/java/com/nononsenseapps/feeder/ui/compose/deletefeed/DeleteFeedScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.requiredHeightIn import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn @@ -32,7 +33,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -107,40 +111,65 @@ fun DeleteFeedDialog( }, title = { Box(modifier = Modifier.fillMaxWidth()) { - val stateLabel = if (selectAllSelected) { - stringResource(androidx.compose.ui.R.string.selected) - } else { - stringResource(androidx.compose.ui.R.string.not_selected) - } + val stateLabel = + if (selectAllSelected) { + stringResource(androidx.compose.ui.R.string.selected) + } else { + stringResource(androidx.compose.ui.R.string.not_selected) + } Text( text = stringResource(id = R.string.delete_feed), style = MaterialTheme.typography.titleMedium, - modifier = Modifier.align(Alignment.CenterStart) + modifier = Modifier.align(Alignment.CenterStart), ) Box(modifier = Modifier.align(Alignment.CenterEnd)) { IconButton(onClick = { menuExpanded = true }) { - Icon(Icons.Default.MoreVert, contentDescription = stringResource(android.R.string.selectAll)) + Icon(Icons.Default.MoreVert, contentDescription = stringResource(R.string.open_menu)) } DropdownMenu(expanded = menuExpanded, onDismissRequest = { menuExpanded = false }) { - DropdownMenuItem(text = { - Row(verticalAlignment = Alignment.CenterVertically) { - Checkbox(checked = selectAllSelected, onCheckedChange = { checked -> - onSelectAll(checked) - menuExpanded = false - }, modifier = Modifier.clearAndSetSemantics { }) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = stringResource(id = android.R.string.selectAll), - style = MaterialTheme.typography.titleMedium, - ) - } - }, onClick = { - onSelectAll(!selectAllSelected) - menuExpanded = false - }, modifier = Modifier.safeSemantics(mergeDescendants = true) { - stateDescription = stateLabel - }) + DropdownMenuItem( + text = { + Row(verticalAlignment = Alignment.CenterVertically) { + Checkbox( + checked = selectAllSelected, + onCheckedChange = { checked -> + onSelectAll(checked) + menuExpanded = false + }, + modifier = Modifier.clearAndSetSemantics { }, + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = stringResource(id = android.R.string.selectAll), + style = MaterialTheme.typography.titleMedium, + ) + } + }, + onClick = { + onSelectAll(!selectAllSelected) + menuExpanded = false + }, + modifier = + Modifier.safeSemantics(mergeDescendants = true) { + stateDescription = stateLabel + }, + ) + val closeMenuText = stringResource(id = R.string.close_menu) + // Hidden button for TalkBack + DropdownMenuItem( + onClick = { + menuExpanded = false + }, + text = {}, + modifier = + Modifier + .height(0.dp) + .safeSemantics { + contentDescription = closeMenuText + role = Role.Button + }, + ) } } } @@ -153,24 +182,25 @@ fun DeleteFeedDialog( feeds.item, key = { feed -> feed.id }, ) { feed -> - val stateLabel = if (isChecked(feed.id)) { - stringResource(androidx.compose.ui.R.string.selected) - } else { - stringResource(androidx.compose.ui.R.string.not_selected) - } + val stateLabel = + if (isChecked(feed.id)) { + stringResource(androidx.compose.ui.R.string.selected) + } else { + stringResource(androidx.compose.ui.R.string.not_selected) + } Row( horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically, modifier = - Modifier - .fillMaxWidth() - .requiredHeightIn(min = minimumTouchSize) - .clickable { - onToggleFeed(feed.id, !isChecked(feed.id)) - } - .safeSemantics(mergeDescendants = true) { - stateDescription = stateLabel - }, + Modifier + .fillMaxWidth() + .requiredHeightIn(min = minimumTouchSize) + .clickable { + onToggleFeed(feed.id, !isChecked(feed.id)) + } + .safeSemantics(mergeDescendants = true) { + stateDescription = stateLabel + }, ) { Checkbox( checked = isChecked(feed.id), @@ -202,10 +232,10 @@ data class DeletableFeed( private fun Preview() = DeleteFeedDialog( feeds = - immutableListHolderOf( - DeletableFeed(1, "A Feed"), - DeletableFeed(2, "Another Feed"), - ), + immutableListHolderOf( + DeletableFeed(1, "A Feed"), + DeletableFeed(2, "Another Feed"), + ), onDismiss = {}, onDelete = {}, )