前言
Compose
中的 TextField()
是 material
风格的输入框, 只得把 BasicTextField
自定义一下。
BasicTextField
的参数这里就不介绍了, 网上介绍的文章已经不少了.
先上图:
自定义的内容有:
左侧的小图标
右侧的删除按钮
hint 空字符时的提示
一、上代码
/**
* @param hint: 空字符时的提示
* @param startIcon: 左侧图标; -1 则不显示
* @param iconSpacing: 左侧图标与文字的距离; 相当于: drawablePadding
*/
@Composable
fun CustomEdit(
text: String = "",
onValueChange: (String) -> Unit,
modifier: Modifier,
hint: String = "请输入",
@DrawableRes startIcon: Int = -1,
iconSpacing: Dp = 6.dp,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
visualTransformation: VisualTransformation = VisualTransformation.None,
cursorBrush: Brush = SolidColor(MaterialTheme.colors.primary)
) {
// 焦点, 用于控制是否显示 右侧叉号
var hasFocus by remember { mutableStateOf(false) }
BasicTextField(
value = text,
onValueChange = onValueChange,
modifier = modifier.onFocusChanged { hasFocus = it.isFocused },
singleLine = true,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
visualTransformation = visualTransformation,
cursorBrush = cursorBrush,
decorationBox = @Composable { innerTextField ->
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
// -1 不显示 左侧Icon
if(startIcon != -1){
Image(painter = painterResource(id = startIcon), contentDescription = null)
Spacer(modifier = Modifier.width(iconSpacing))
}
Box(modifier = Modifier.weight(1f)){
// 当空字符时, 显示hint
if(text.isEmpty())
Text(text = hint, color = GrayAa, style = textStyle)
// 原本输入框的内容
innerTextField()
}
// 存在焦点 且 有输入内容时. 显示叉号
if(hasFocus && text.isNotEmpty()) {
Image(imageVector = Icons.Filled.Clear, // 清除图标
contentDescription = null,
// 点击就清空text
modifier = Modifier.clickable { onValueChange.invoke("") })
}
}
}
)
}
二、使用
// vm : ViewModel;
// 手机号输入框
CustomEdit(
text = vm.phone,
onValueChange = {
vm.phone = it
},
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, top = 20.dp, end = 16.dp)
.height(50.dp)
.background(GrayE5, shape = MaterialTheme.shapes.medium)
.padding(horizontal = 16.dp),
hint = "请输入手机号",
startIcon = R.drawable.ic_login_phone,
iconSpacing = 16.dp,
textStyle = Typography.body1,
// keyboardType -> 半个 inputType; 这里是 Phone
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone),
)
// code 输入框
CustomEdit(
text = vm.code,
onValueChange = {
vm.code = it
},
modifier = Modifier
.fillMaxSize()
.background(GrayE5, shape = MaterialTheme.shapes.medium)
.padding(horizontal = 16.dp),
hint = "请输入验证码",
startIcon = R.drawable.ic_login_pwd,
iconSpacing = 16.dp,
textStyle = Typography.body1,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
)
三、只有hint的 BasicTextField
1. 自定义CustomEditHint
/**
* 只增加 hint; 适合多行输入框, 没有前后Icon的小输入框; 背景 尺寸等 定义在modifier中;
* @param hint: 空字符时的提示
*/
@Composable
fun CustomEditHint(
text: String = "",
onValueChange: (String) -> Unit,
modifier: Modifier,
hint: String = "请输入",
enabled: Boolean = true,
readOnly: Boolean = false,
singleLine: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
visualTransformation: VisualTransformation = VisualTransformation.None,
cursorBrush: Brush = SolidColor(MaterialTheme.colors.primary)
) {
// 焦点, 用于控制是否显示 右侧叉号
BasicTextField(
value = text,
onValueChange = onValueChange,
modifier = modifier,
singleLine = singleLine,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
visualTransformation = visualTransformation,
cursorBrush = cursorBrush,
decorationBox = @Composable { innerTextField ->
if(text.isEmpty())
Text(text = hint, color = GrayAa, style = textStyle)
innerTextField()
}
)
}
2.Preview
@Preview(showBackground = true)
@Composable
fun TextFieldViewPreview() {
val scrollState = rememberScrollState()
Column(
modifier = Modifier.verticalScroll(scrollState)
) {
var text by remember { mutableStateOf("") }
// 带前icon 及 后清除icon 的输入框
CustomEdit(
text = text,
onValueChange = {
text = it.trim()
},
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, top = 20.dp, end = 16.dp)
.height(50.dp)
.background(GrayE5, shape = MaterialTheme.shapes.medium)
.padding(horizontal = 16.dp),
hint = "请输入手机号",
iconSpacing = 16.dp,
textStyle = TextDark16,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(onSearch = {
ComApplication.INSTANCES.toast("搜索:$text")
}),
)
// 多行输入框
CustomEditHint(
text = text,
onValueChange = {
text = it.trim()
},
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp)
.height(200.dp)
.background(GrayE5)
.padding(horizontal = 14.dp, vertical = 12.dp),
hint = "请输入详情",
)
// 小输入框
var text2 by remember { mutableStateOf("") }
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.White)
.padding(14.dp)
){
Text(text = "联系方式", style = TextDarkBlod14)
CustomEditHint(
text = text2,
onValueChange = {
text2 = it.trim().let { str ->
// maxLength = 15
if(str.length > 15){
str.substring(0, 15)
} else {
str
}
}
},
modifier = Modifier
.align(Alignment.CenterEnd)
.defaultMinSize(100.dp, 14.dp),
hint = "手机或邮箱都可以哦",
singleLine = true,
textStyle = TextStyle.Default.copy(textAlign = TextAlign.End)
)
}
}
}
总结
没有总结!
上一篇: 记一次自定义View:滑动标尺
下一篇: Compose-navigation: 问题汇总