【问题标题】:Jetpack Compose - Disable TextField long press handlerJetpack Compose - 禁用 TextField 长按处理程序
【发布时间】:2021-10-13 01:17:09
【问题描述】:

我在trailingIconOutlinedTextField 中有一个IconButton,例如:

OutlinedTextField(
    modifier = Modifier.weight(1f),
    label = { Text(text = "Label") },
    value = text,
    onValueChange = { text = it },
    trailingIcon = {
        IconButton2(onClick = {
            println("onClick")
        }, onLongClick = {
            println("onLongClick shows TextToolbar")
        }) {
            Icon(
                imageVector = Icons.Filled.Menu,
                contentDescription = null
            )
        }
    }
)

IconButton2 只是IconButton 的副本,但combinedClickable 包含onLongClick 而不是clickable

问题是当我长按IconButton2 时,它显示TextToolbar 对应TextField。不管我做什么,文本字段都会处理长按,显示TextToolbar 并提供触觉反馈。

即使我将pointerInputawaitPointerEventconsumeAllChanges(如here)一起使用,它仍然会触发它。 TextField 不响应任何点击或任何东西,但如果我长按它,它就会响应!

我现在正在做的解决方法是将文本字段包装在 Row 中,并在其旁边添加 IconButton 而不是“内部”,但我需要将图标按钮设置为 trailingIcon

有什么方法可以正确地做到吗?

Compose 1.0.3 和 1.1.0-alpha05 的行为相同。

【问题讨论】:

    标签: kotlin android-jetpack-compose


    【解决方案1】:

    我最终做了一个看起来工作正常的小技巧,所以基本上我添加了一个虚拟 Box 作为 trailingIcon 来获取它的位置,然后我在它外面添加了一个 IconButton(都包裹在一个 Box 中)和我也得到了它的位置+我使用虚拟框的位置来偏移它。不是理想的解决方案,但效果很好。

    如果有人需要,这里是完整的来源:

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                MyApplicationTheme {
                    Surface(
                        modifier = Modifier.padding(16.dp),
                        color = MaterialTheme.colors.background
                    ) {
                        var text by remember { mutableStateOf("") }
                        var trailingIconOffset by remember { mutableStateOf(Offset.Zero) }
                        var iconButtonOffset by remember { mutableStateOf(Offset.Zero) }
                        val colors = TextFieldDefaults.outlinedTextFieldColors()
    
                        Column {
                            //With hack
                            Box {
                                OutlinedTextField(
                                    modifier = Modifier.fillMaxWidth(),
                                    label = { Text(text = "With hack") },
                                    value = text,
                                    onValueChange = { text = it },
                                    trailingIcon = {
                                        Box(modifier = IconButtonSizeModifier
                                            .onGloballyPositioned {
                                                trailingIconOffset = it.positionInRoot()
                                            }
                                        )
                                    },
                                    colors = colors
                                )
    
                                val contentColor by colors.trailingIconColor(
                                    enabled = true,
                                    isError = false
                                )
    
                                CompositionLocalProvider(
                                    LocalContentColor provides contentColor,
                                    LocalContentAlpha provides contentColor.alpha
                                ) {
                                    IconButton2(
                                        modifier = Modifier
                                            .onGloballyPositioned {
                                                iconButtonOffset = it.positionInRoot()
                                            }
                                            .absoluteOffset {
                                                IntOffset(
                                                    (trailingIconOffset.x - iconButtonOffset.x).toInt(),
                                                    (trailingIconOffset.y - iconButtonOffset.y).toInt()
                                                )
                                            },
                                        onClick = {
                                            text = "onClick"
                                        },
                                        onLongClick = {
                                            text = "onLongClick"
                                        }
                                    ) {
                                        Icon(imageVector = Icons.Filled.Menu, contentDescription = null)
                                    }
                                }
                            }
    
                            //Without hack
                            Box {
                                OutlinedTextField(
                                    modifier = Modifier.fillMaxWidth(),
                                    label = { Text(text = "Without hack") },
                                    value = text,
                                    onValueChange = { text = it },
                                    trailingIcon = {
                                        IconButton2(
                                            onClick = {
                                                text = "onClick"
                                            },
                                            onLongClick = {
                                                text = "onLongClick"
                                            }
                                        ) {
                                            Icon(
                                                imageVector = Icons.Filled.Menu,
                                                contentDescription = null
                                            )
                                        }
                                    },
                                    colors = colors
                                )
                            }
                        }
                    }
                }
            }
        }
    }
    
    private val RippleRadius = 24.dp
    private val IconButtonSizeModifier = Modifier.size(48.dp)
    
    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    fun IconButton2(
        modifier: Modifier = Modifier,
        onClick: () -> Unit,
        onLongClick: (() -> Unit)? = null,
        enabled: Boolean = true,
        interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
        content: @Composable () -> Unit
    ) {
        Box(
            modifier = modifier
                .combinedClickable(
                    onClick = onClick,
                    onLongClick = onLongClick,
                    enabled = enabled,
                    role = Role.Button,
                    interactionSource = interactionSource,
                    indication = rememberRipple(bounded = false, radius = RippleRadius)
                )
                .then(IconButtonSizeModifier),
            contentAlignment = Alignment.Center
        ) {
            val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled
            CompositionLocalProvider(LocalContentAlpha provides contentAlpha, content = content)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-15
      • 2022-11-21
      • 2021-11-16
      • 1970-01-01
      • 2021-11-14
      • 2023-02-04
      • 2022-10-16
      • 1970-01-01
      相关资源
      最近更新 更多