Compose的TextField默认不支持hint效果,虽然可以通过设置textcolor和text为空时的默认值来实现hint效果,但无法添加图标。
而OutlinedTextField虽然可以实现placeholder效果,但是会有内置padding无法移除
于是着手于BasicTextField,尝试通过自定义BasicTextField的方式实现hint。在查看BasicTextField()构造方法的时候发现有名为decorationBox的参数:
fun BasicTextField(
value: String,
...,
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
)
decorationBox - Composable lambda that allows to add decorations around text field, such as icon, placeholder, helper messages or similar, and automatically increase the hit target area of the text field. To allow you to control the placement of the inner text field relative to your decorations, the text field implementation will pass in a framework-controlled composable parameter "innerTextField" to the decorationBox lambda you provide. You must call innerTextField exactly once.
查看注释说明,decorationBox就是用来给输入框做自定义提示效果的,并且提供了一个innerTextField作为默认实现,这个innerTextField就是输入框自身的内容
知道这些后就可以自定义placeholder的实现了。例如:
BasicTextField(
value = text,
...,
) { innerTextField ->
if (text.isEmpty()) {
// 自定义placeholder
} else {
innerTextField()
}
}
但是这样实现会存在一个问题,就是当输入框获得焦点时,输入框的UI没有任何呈现,导致用户不知道可以输入内容了。做出修改后如下:
BasicTextField(
value = text,
) {
innerTextField ->
if (text.isEmpty()) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
// 自定义placeholder
innerTextField()
}
} else {
innerTextField()
}
}