android 检测合成文本字段中的点击

lrl1mhuk  于 2023-03-28  发布在  Android
关注(0)|答案(4)|浏览(140)

我正在尝试为合成TextField实现onClick处理程序。当前功能是处理TextField单击,但禁用字段的手动编辑。对于我的用例,我希望处理单击并执行其他操作。我希望保持TextField的外观和感觉,并希望焦点动画也发生。
readOnly属性从UX的Angular 给出了我想要的东西,但是当我点击TextField时,onClick处理程序没有被调用。

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

我也试过使用pointerInput,我是如何有同样的问题。

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

由于Compose是如此的新,很难判断这是一个bug还是故意的。

qmb5sa22

qmb5sa221#

也许检测文本字段中的点击事件的更好方法是使用交互源。
第一步:-创建交互源

val source = remember {
    MutableInteractionSource()
}

第二步:-传递到文本字段

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))
)

步骤:3-收集按下的流作为状态,并观察其变化。

if ( source.collectIsPressedAsState().value)
        onClicked()
k5ifujac

k5ifujac2#

使用readOnly = true时,TextField仍处于启用状态,第一次单击将焦点放在该字段上。您必须执行双击以处理onClick功能。
否则,您可以使用enabled属性:

TextField(
        enabled = false,
        modifier = Modifier.clickable(onClick = {/* ... */})
    )

比如:

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)
    )
)

31moq8wy

31moq8wy3#

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

if ( source.collectIsPressedAsState().value)
    onClicked()

即使按下canceledonClicked()也会触发,因为你没有等待看到按下后的结束状态。当你滚动时,如果你的触摸与textField的位置相同,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)))
    }

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

unhi4e5o

unhi4e5o4#

正确的答案应该是使用InteractionSourceinteractions,而不是collectIsPressedAsState!最后一个答案只是检查你点击什么,但它忽略了你甚至没有松开手指的事实

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

https://stackoverflow.com/a/70335041/7767664开始

相关问题