Jetpack Compose:可点击的 TextField 不起作用

and*_*boy 31 android android-jetpack-compose android-compose-textfield

由于某种原因,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)
                    }
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我想出了一个糟糕的解决方案onFocusChanged,但效果不佳。

对于那些需要上下文的人,我正在尝试执行 ExusedDropdown 但我希望当我单击 TextField 上的任意位置时打开它

bei*_*rad 37

另一种可能的解决方法是:

import kotlinx.coroutines.flow.collect

TextField(
    value = ...,
    onValueChange = { ... },
    interactionSource = remember { MutableInteractionSource() }
        .also { interactionSource ->
            LaunchedEffect(interactionSource) {
                interactionSource.interactions.collect {
                    if (it is PressInteraction.Release) {
                        // works like onClick
                    }
                }
            }
        }
)

Run Code Online (Sandbox Code Playgroud)

  • 所以其他人不会偶然发现这一点,请确保使用“import kotlinx.coroutines.flow.collect”作为collect的来源,否则你会得到一个奇怪的异常。显然 kotlin 的某个人决定在同一个库中使用第二种名为“collect”的方法 XD (6认同)
  • 值得注意的是:并不强制设置 `enabled = false` 来接收回调。 (2认同)
  • 如何添加涟漪效果? (2认同)

Эва*_*ist 25

对于 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
    )
}
Run Code Online (Sandbox Code Playgroud)

要消除涟漪效应,请使用此类扩展

inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit): Modifier =
    composed {
        clickable(indication = null,
            interactionSource = remember { MutableInteractionSource() }) {
            onClick()
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 为什么我们必须让“enabled = false”才能让“clickable”起作用? (2认同)
  • 发现这个错误,概述了原因 https://issuetracker.google.com/issues/172154008 - 如果您认为这应该以不同的方式工作,请加星标/评论 (2认同)

Noa*_*h O 14

将启用属性设置为 false 的建议有效,但这会影响样式。如果您希望它在视觉上与启用的 TextField 匹配,请相应地设置颜色属性:

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)
)
Run Code Online (Sandbox Code Playgroud)


Ros*_*han 9

val interactionSource = remember { MutableInteractionSource() }
val isPressed: Boolean by interactionSource.collectIsPressedAsState()

LaunchedEffect(isPressed){
    if (isPressed) {
        // Click action
    }
}

TextField(
value = textFieldValue,
onValueChange = onTextFieldChange,
interactionSource = interactionSource
)
Run Code Online (Sandbox Code Playgroud)


Gab*_*tti 8

修饰符clickable当前 ( 1.0.0-beta08) 不适用于TextField.

这是一种解决方法,而不是真正的解决方案。
由于您TextField是只读的,因此您可以将 包裹OutlinedTextField在 a 中Box,使用第二个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
                ))
        }
    }
Run Code Online (Sandbox Code Playgroud)