[英]Jetpack Compose: TextField clickable does not work
出于某种原因,Compose TextField 的点击侦听器对我不起作用。
@Composable
private fun ExposedDropdown(
modifier: Modifier,
list: List<String>,
priority: Int
) {
var expanded by remember { mutableStateOf(false) }
Column(modifier) {
OutlinedTextField(
value = list[priority],
onValueChange = { },
readOnly = true,
singleLine = true,
label = { Text(stringResource(id = R.string.status)) },
modifier = Modifier
.fillMaxWidth()
.clickable { Timber.i("Not working :(") }
.onFocusChanged { if (it.isFocused) expanded = !expanded },
trailingIcon = {
Icon(
imageVector = Icons.Outlined.ArrowDropDown,
contentDescription = null,
modifier = Modifier
.clickable { expanded = !expanded }
.padding(16.dp)
)
}
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
list.forEach { label ->
DropdownMenuItem(onClick = {
viewModel.setPriority(list.indexOf(label))
expanded = false
}) {
Text(text = label)
}
}
}
}
}
如您所见,我使用onFocusChanged
提出了糟糕的解决方案,但效果不佳。
对于那些需要上下文的人,我正在尝试做 ExposedDropdown 但我希望它在我单击 TextField 上的任意位置时打开
当前的clickable
修饰符( 1.0.0-beta08
)不适用于TextField
。
这是一种解决方法,而不是真正的解决方案。
由于您的TextField
是只读的,因此您可以使用第二个Box
将OutlinedTextField
包装在一个Box
中以处理单击。
val (focusRequester) = FocusRequester.createRefs()
val interactionSource = remember { MutableInteractionSource() }
Box() {
OutlinedTextField(
//...your code
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
}
if (!expanded) {
Box(modifier = Modifier
.matchParentSize()
.clickable(
onClick = {
expanded = !expanded
focusRequester.requestFocus() //to give the focus to the TextField
},
interactionSource = interactionSource,
indication = null //to avoid the ripple on the Box
))
}
}
将 enabled 属性设置为 false 的建议有效,但这会影响样式。 如果您希望它在视觉上与启用的 TextField 匹配,则相应地设置 colors 属性:
OutlinedTextField(
value = "Example",
enabled = false,
onValueChange = {},
modifier = Modifier.clickable { doSomeBehavior() },
colors = TextFieldDefaults.outlinedTextFieldColors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
disabledBorderColor = MaterialTheme.colorScheme.outline,
disabledPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant,
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
//For Icons
disabledLeadingIconColor = MaterialTheme.colorScheme.onSurfaceVariant,
disabledTrailingIconColor = MaterialTheme.colorScheme.onSurfaceVariant)
)
使用 compose 1.0.2它默认工作。 需要添加行enabled = false
例子
@Composable
fun SelectableTextField(
modifier: Modifier = Modifier,
textValue: String,
onClick: () -> Unit
) {
TextField(
value = textValue,
onValueChange = {},
modifier = modifier
.fillMaxWidth()
.clickable { onClick() },
enabled = false
)
}
要消除涟漪效应,请使用此类扩展
inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit): Modifier =
composed {
clickable(indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
这是一个可能的解决方案。 我创建了一个基于androidx.compose.foundation.interaction.collectIsPressedAsState
可组合的collectClickAsState()
:
@Composable
fun CustomTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
onClick: (() -> Unit)? = null,
) {
val onClickSource = remember { MutableInteractionSource() }
if (onClick != null) {
if (onClickSource.collectClickAsState().value) {
onClick.invoke()
}
}
TextField(
value = value,
onValueChange = onValueChange,
interactionSource = onClickSource,
enabled = enabled,
readOnly = onClick != null,
modifier = modifier
// add clickable to work with talkback/accessibility
.clickable(enabled = enabled) { onClick?.invoke() },
)
}
@Composable
fun InteractionSource.collectClickAsState(): State<Boolean> {
val onClick = remember { mutableStateOf(false) }
LaunchedEffect(this) {
var wasPressed = false
interactions.collect { interaction ->
when (interaction) {
is PressInteraction.Press -> {
wasPressed = true
}
is PressInteraction.Release -> {
if (wasPressed) onClick.value = true
wasPressed = false
}
is PressInteraction.Cancel -> {
wasPressed = false
}
}
// reset state with some delay otherwise it can re-emit the previous state
delay(10L)
onClick.value = false
}
}
return onClick
}
使用此解决方案,文本字段仍然是可聚焦的,文本是可选择的,它将使用启用了正确 UI 的 state。
另一种可能的解决方法是:
TextField(
value = ...,
onValueChange = { ... },
interactionSource = remember { MutableInteractionSource() }
.also { interactionSource ->
LaunchedEffect(interactionSource) {
interactionSource.interactions.collect {
if (it is PressInteraction.Release) {
// works like onClick
}
}
}
}
)
收听TextField点击动作的简单解决方案
val interactionSource = remember { MutableInteractionSource() }
val isPressed: Boolean by interactionSource.collectIsPressedAsState()
if (isPressed) {
// Click action
}
TextField(
value = textFieldValue,
onValueChange = onTextFieldChange,
interactionSource = interactionSource
)
TextField(
modifier = Modifier
.fillMaxWidth()
.**clickable**(onClick = onClick),
enabled = false,
value = currentSelection,
onValueChange = { },
label = {
}
)
使用 enabled = false 和 clickable 修饰符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.