Added semantics to the invisible box
contentDescription - provides current state info TODO: add translations
This commit is contained in:
@@ -50,6 +50,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.onClick
|
||||||
|
import androidx.compose.ui.semantics.role
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
import androidx.compose.ui.semantics.stateDescription
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
@@ -59,13 +65,13 @@ import kotlinx.collections.immutable.ImmutableList
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TextSpinner(
|
fun TextSpinner(
|
||||||
label: String?,
|
modifier: Modifier = Modifier,
|
||||||
|
label: String? = null,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
options: ImmutableList<TitleExplainer>,
|
options: ImmutableList<TitleExplainer>,
|
||||||
onSelect: (Int) -> Unit,
|
onSelect: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
) {
|
||||||
TextSpinner(
|
BaseTextSpinner(
|
||||||
placeholder,
|
placeholder,
|
||||||
options,
|
options,
|
||||||
onSelect,
|
onSelect,
|
||||||
@@ -89,12 +95,36 @@ fun TextSpinner(
|
|||||||
onSelect: (Int) -> Unit,
|
onSelect: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit,
|
mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit,
|
||||||
|
) {
|
||||||
|
BaseTextSpinner(
|
||||||
|
placeholder = placeholder,
|
||||||
|
options = options,
|
||||||
|
onSelect = onSelect,
|
||||||
|
modifier = modifier,
|
||||||
|
mainElement = mainElement,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BaseTextSpinner(
|
||||||
|
placeholder: String,
|
||||||
|
options: ImmutableList<TitleExplainer>,
|
||||||
|
onSelect: (Int) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
mainElement: @Composable (currentOption: String, modifier: Modifier) -> Unit,
|
||||||
) {
|
) {
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
var optionsShowing by remember { mutableStateOf(false) }
|
var optionsShowing by remember { mutableStateOf(false) }
|
||||||
var currentText by remember(placeholder) { mutableStateOf(placeholder) }
|
var currentText by remember(placeholder) { mutableStateOf(placeholder) }
|
||||||
|
|
||||||
|
val accessibilityDescription =
|
||||||
|
if (currentText == placeholder) {
|
||||||
|
"Dropdown menu, $placeholder, not selected"
|
||||||
|
} else {
|
||||||
|
"Dropdown menu, $currentText selected"
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
@@ -105,13 +135,23 @@ fun TextSpinner(
|
|||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.matchParentSize().clickable(
|
Modifier
|
||||||
interactionSource = interactionSource,
|
.matchParentSize()
|
||||||
indication = null,
|
.clickable(
|
||||||
) {
|
interactionSource = interactionSource,
|
||||||
optionsShowing = true
|
indication = null,
|
||||||
focusRequester.requestFocus()
|
) {
|
||||||
},
|
optionsShowing = true
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}.semantics {
|
||||||
|
role = Role.DropdownList
|
||||||
|
stateDescription = accessibilityDescription
|
||||||
|
onClick(label = "Open dropdown menu") {
|
||||||
|
optionsShowing = true
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
return@onClick true
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +228,15 @@ fun <T> SpinnerSelectionDialog(
|
|||||||
}
|
}
|
||||||
itemsIndexed(options) { index, item ->
|
itemsIndexed(options) { index, item ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth().clickable { onSelect(index) }.padding(16.dp, 16.dp),
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onSelect(index) }
|
||||||
|
.padding(16.dp, 16.dp)
|
||||||
|
.semantics {
|
||||||
|
role = Role.Button
|
||||||
|
contentDescription = "Option ${index + 1} of ${options.size}"
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
Column { onRenderItem(item) }
|
Column { onRenderItem(item) }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user