检测撰写文本字段中的点击

los*_*ion 22 android kotlin android-jetpack-compose android-compose-textfield

我正在尝试为 Compose TextField 实现 onClick 处理程序。当前功能是处理文本字段单击,但禁用手动编辑字段。对于我的用例,我想处理点击并执行其他操作。我想保持 TextField 的外观和感觉,并希望焦点动画也能发生。

readOnly 属性为我提供了从 UX 角度来看我想要的内容,但是当我单击 TextField 时,不会调用 onClick 处理程序。

TextField(
  value = text,
  onValueChange = { text = it},
  readOnly = true,
  modifier = Modifier
    .clickable(onClick = {
      Log.i("TextField", "Clicked")
    })
)
Run Code Online (Sandbox Code Playgroud)

我也尝试过使用pointerInput,我怎么也遇到同样的问题。

TextField(
  value = text,
  onValueChange = { text = it},
  readOnly = true,
  modifier = Modifier
    .pointerInput(Unit) {
      detectTapGestures(onTap = {
        Log.i("TextField", "Clicked")
      }
    }
)
Run Code Online (Sandbox Code Playgroud)

由于 Compose 如此之新,很难判断这是一个错误还是有意为之。

Gab*_*tti 19

使用readOnly = trueTextField处于启用状态,第一次单击会将焦点移至该字段。您必须执行双击才能处理您的onClick功能。

否则你可以使用该enabled属性:

   TextField(
        enabled = false,
        modifier = Modifier.clickable(onClick = {/* ... */})
    )
Run Code Online (Sandbox Code Playgroud)

就像是:

TextField(
    value = text,
    onValueChange = { text = it},
    enabled = false,
    modifier = Modifier
        .clickable { text= "Clicked"},
    colors = TextFieldDefaults.textFieldColors(
        disabledTextColor = LocalContentColor.current.copy(LocalContentAlpha.current),
        disabledLabelColor =  MaterialTheme.colors.onSurface.copy(ContentAlpha.medium)
    )
)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Zak*_*ikh 18

也许检测文本字段中的点击事件的更好方法是使用交互源。

步骤 1: -创建交互源

 val source = remember {
    MutableInteractionSource()
}
Run Code Online (Sandbox Code Playgroud)

第 2 步:- 将其传递到文本字段

 OutlinedTextField(
    value = text,
    readOnly = true,
    onValueChange = {},
    textStyle = MaterialTheme.typography.body1.copy(
        lineHeight = if (isFocused) 25.sp else TextUnit.Unspecified,
        fontWeight = if (isFocused) FontWeight.SemiBold else FontWeight.Normal
    ),
    label = {
        Text(
            text = label,
            fontWeight = if (isFocused) FontWeight.SemiBold else FontWeight.Normal,
            style = MaterialTheme.typography.caption
        )
    },
    interactionSource = source,
    colors = TextFieldDefaults.outlinedTextFieldColors(
        textColor = if (isFocused) MaterialTheme.colors.primary else LocalContentColor.current
    ),
    maxLines = if (isFocused) Int.MAX_VALUE else 2,
    modifier = Modifier
        .padding(
            start = COUNTER_WIDTH + 16.dp,
            top = padding,
            bottom = padding,
            end = 16.dp
        )
        .fillMaxWidth()
        .verticalScroll(enabled = isFocused, state = rememberScrollState())
        .animateContentSize(animationSpec = tween(DURATION))
)
Run Code Online (Sandbox Code Playgroud)

步骤:3-收集加压流量作为状态并观察其变化。

 if ( source.collectIsPressedAsState().value)
        onClicked()
Run Code Online (Sandbox Code Playgroud)

  • @rewgoes我认为有副作用/sf/answers/5161855821/ (5认同)

use*_*924 12

正确的答案是使用interactionsofInteractionSource而不是collectIsPressedAsState!最后一个只是检查您何时点击某物,但它忽略了您甚至没有松开手指的事实

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)

来自/sf/answers/4923452901/


Far*_*nov 8

对我来说,最重要的答案似乎有一个主要问题。

if ( source.collectIsPressedAsState().value)
    onClicked()
Run Code Online (Sandbox Code Playgroud)

onClicked()即使按下也会触发,canceled因为您没有等待按下后看到结束状态。当您滚动时,如果您的触摸位置与文本字段相同,则会触发 onClick,我确信 99% 的情况下这都是不需要的交互。

val pressedState=source.interactions.collectAsState(
      initial = PressInteraction.Cancel(PressInteraction.Press(Offset.Zero)))
       
    if (pressedState.value is PressInteraction.Release)
    {
        dropDownExpanded.value = true
        onClick?.invoke()
        source.tryEmit(PressInteraction.Cancel(PressInteraction.Press(Offset.Zero)))
    }
Run Code Online (Sandbox Code Playgroud)

如果你这样做,它会消除滚动时不需要的 onClick