使用 BasicTextField(Jetpack Compose) 时,粘贴字段的位置出现问题

3
我在 Jetpack Compose (1.4.2) 中设置了一个普通的 BasicTextField。
如果我想要粘贴之前复制的文本,该字段会出现在奇怪的位置(左上角)。我该如何解决?
更新:提供了 BasicTextField 实现的代码。
@Composable
fun CustomTextField(
    value: String,
    placeholder: String,
    enabled: Boolean = true,
    loading: Boolean = false,
    keyboardType: KeyboardType,
    update: ((String) -> Unit)? = null
) {

    var focus by remember {
        mutableStateOf(false)
    }

    BasicTextField(
        value = value,
        onValueChange = { new ->
            update?.let {
                it(new)
            }
        },
        cursorBrush = SolidColor(Blue),
        textStyle = MaterialTheme.typography.bodyMedium,
        decorationBox = { inner ->
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(
                        start = 16.dp,
                        end = 16.dp
                    ),
                contentAlignment = Alignment.CenterStart
            ) {
                if (value.isEmpty()) {
                    Text(
                        text = placeholder,
                        style = MaterialTheme.typography.bodyMedium,
                        color = Blue_2
                    )
                } else {
                    Row(
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.SpaceBetween,
                        modifier = Modifier
                            .fillMaxWidth()
                    ) {
                        inner()

                        if (loading) {
                            Box(
                                modifier = Modifier
                                    .padding(vertical = 24.dp, horizontal = 16.dp)
                                    .size(16.dp)
                            ) {
                                CircularProgressIndicator(
                                    color = Blue_6
                                )
                            }
                        }
                    }
                }
            }
        },
        visualTransformation = if (keyboardType == KeyboardType.Password) PasswordVisualTransformation() else VisualTransformation.None,
        keyboardOptions = KeyboardOptions(
            keyboardType = keyboardType
        ),
        enabled = enabled,
        modifier = Modifier
            .fillMaxWidth()
            .shadow(
                elevation = if (focus) 15.dp else 7.5.dp,
                shape = RoundedCornerShape(16.dp),
                clip = false,
                ambientColor = Blue_6,
                spotColor = Blue_6
            )
            .background(
                if (focus) Focused else Not_Focused,
                RoundedCornerShape(16.dp)
            )
            .height(60.dp)
            .onFocusChanged {
                focus = it.hasFocus
            },
        singleLine = true
    )
}

enter image description here


1
你能提供这个文本框的代码吗?似乎在实现自定义文本框时有些东西遗漏了。 - Merkost
根据您的请求提供此内容。 - lr058
2个回答

1

你应该每次都使用Textfield的inner()函数

问题出在你的占位符语句上,以下是详细信息:

if (value.isEmpty()) {
    Text(
        text = placeholder,
        style = MaterialTheme.typography.bodyMedium,
        color = Blue
    )
} else {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier
            .fillMaxWidth()
    ) {
        //This inner function should not be a part of the value.isEmpty() condition
        inner()
    }
}

使用 if (value.isEmpty()) 条件,您没有实现 inner() 文本字段函数。当您的文本为空时,文本字段不存在,粘贴菜单出现在坐标轴原点(左上角)。

这里有一个正常工作的示例供您参考:

@Composable
fun CustomTextField(
    value: String,
    placeholder: String,
    enabled: Boolean = true,
    loading: Boolean = false,
    keyboardType: KeyboardType,
    update: ((String) -> Unit)? = null
) {

    var focus by remember {
        mutableStateOf(false)
    }

    BasicTextField(
        value = value,
        onValueChange = { new ->
            update?.let {
                it(new)
            }
        },
        cursorBrush = SolidColor(Blue),
        textStyle = MaterialTheme.typography.bodyMedium,
        decorationBox = { inner ->
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(
                        start = 16.dp,
                        end = 16.dp
                    ),
                contentAlignment = Alignment.CenterStart
            ) {
                inner()

                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.SpaceBetween,
                    modifier = Modifier
                        .fillMaxWidth()
                ) {

                    if (loading) {
                        Box(
                            modifier = Modifier
                                .padding(vertical = 24.dp, horizontal = 16.dp)
                                .size(16.dp)
                        ) {
                            CircularProgressIndicator(
                                color = Blue
                            )
                        }
                    }
                }
            
                if (value.isEmpty()) {
                    Text(
                        text = placeholder,
                        style = MaterialTheme.typography.bodyMedium,
                        color = Blue
                    )
                }
            }
        },
        visualTransformation = if (keyboardType == KeyboardType.Password) PasswordVisualTransformation() else VisualTransformation.None,
        keyboardOptions = KeyboardOptions(
            keyboardType = keyboardType
        ),
        enabled = enabled,
        modifier = Modifier
            .fillMaxWidth()
            .shadow(
                elevation = if (focus) 15.dp else 7.5.dp,
                shape = RoundedCornerShape(16.dp),
                clip = false,
                ambientColor = Blue,
                spotColor = Blue
            )
            .background(
                if (focus) Color.Cyan else Color.Green,
                RoundedCornerShape(16.dp)
            )
            .height(60.dp)
            .onFocusChanged {
                focus = it.hasFocus
            },
        singleLine = true
    )
}

0
如Merkost所说,每次都应该使用Textfield的inner()函数。
但是如果你希望文本框不可见,可以这样包装:
BasicTextField(...) { innerTextField -> 
    CompositionLocalProvider(
            LocalTextSelectionColors.provides(
                TextSelectionColors(
                    Color.Transparent,
                    Color.Transparent
                )
            )
        ) {
            Box(modifier = Modifier.drawWithContent { }) {
                innerTextField()
            }
        }
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接