Jetpack compose - 60行代码实现正方形验证码输
2021-10-21 本文已影响0人
luowenbin
实现效果
总的来说就是对输入框显示进行重绘
img.png1.监听用户输入
TextField是Jetpack compose中获取用户输入内容的常用输入框。
在此我们只需要获取输入法输入内容就行,不需要外观,因此使用BasicTextField即可。
验证码码一般都是纯数字组成,通过KeyboardOptions 的keyboardType来限制输入内容为数字(类似于EditText 的inputType)
但是还需要隐藏输入回显的文本,因此使用Modifier.drawWithContent { }
重新覆盖绘制,就能去掉了。
var content by remember { mutableStateOf("") }
BasicTextField(
value = content,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),//设置仅输入数字
onValueChange = {
content = it//保存用户输入的内容
},
modifier = Modifier
.drawWithContent { }//清除绘制内容
.matchParentSize()//填充至父布局大小
)
还需要响应点击调起输入法的效果,因此可以利用Box将BasicTextField覆盖在我们的重绘的控件上。用户点击的时候实际点击在BasicTextField上便能自动调起输入法。
Box {
//重新绘制的验证码输入框
BasicTextField(...
}
2.绘制验证码内容
接下来就是根据输入内容content进行重新绘制
验证码输入框的UI就是横着的一排矩形,使用一个Row完成,然后适当在中间加一些间距。
为了使得矩形框的样式更加灵活,可以将矩形框绘制通过Composable参数向上暴露。
Row(horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically) {
repeat(digits) {//根据矩形框数量绘制
if (it != 0) {
//在中间添加间距
Spacer(modifier = Modifier.width(horizontalMargin))
}
//获取当前框的文本
val text = content.getOrNull(it)?.toString() ?: ""
//是否正在输入的框
val focused = it == content.length
//绘制文本
itemScope(text, focused)
}
}
然后完成单个矩形框的绘制,使用Text将验证码文本绘制出来就行,由于没发现使Text文本垂直居中的Modifier,所以套上了一个Box。
@Composable
fun SimpleVerificationCodeItem(text: String, focused: Boolean) {
val borderColor = if (focused) Color.Gray else Color(0xeeeeeeee)
Box(
modifier = Modifier
.border(1.dp, borderColor)
.size(55.dp, 55.dp), contentAlignment = Alignment.Center
) {
Text(
text = text,
fontSize = 24.sp,
textAlign = TextAlign.Center,
maxLines = 1
)
}
}
完整代码
验证码输入框
/**
* @param text 文本内容
* @param focused 是否高亮当前输入框
*/
@Composable
fun SimpleVerificationCodeItem(text: String, focused: Boolean) {
val borderColor = if (focused) Color.Gray else Color(0xeeeeeeee)
Box(
modifier = Modifier
.border(1.dp, borderColor)
.size(55.dp, 55.dp), contentAlignment = Alignment.Center
) {
Text(
text = text,
fontSize = 24.sp,
textAlign = TextAlign.Center,
maxLines = 1
)
}
}
/**
* @param digits 验证码位数(框数量)
* @param horizontalMargin 水平间距
* @param inputCallback 输入回调
*/
@Composable
fun VerificationCodeField(
digits: Int,
horizontalMargin: Dp = 10.dp,
inputCallback: (content: String) -> Unit = {},
itemScope: @Composable (text: String, focused: Boolean) -> Unit
) {
var content by remember { mutableStateOf("") }
Box {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
//绘制框
repeat(digits) {
if (it != 0) {
//添加间距
Spacer(modifier = Modifier.width(horizontalMargin))
}
//获取当前框的文本
val text = content.getOrNull(it)?.toString() ?: ""
//是否正在输入的框
val focused = it == content.length
//绘制文本
itemScope(text, focused)
}
}
BasicTextField(value = content, onValueChange = {
content = it
inputCallback(it)
}, modifier = Modifier
.drawWithContent { }//清楚绘制内容
.matchParentSize())//填充至父布局大小
}
}
使用方法
VerificationCodeField(5){text,focused->
SimpleVerificationCodeItem(text,focused)
}