You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Compose中实现OTP验证码输入布局?

Jetpack Compose OTP输入布局实现方案

以下实现完全基于原生Compose组件开发,无需引入第三方依赖,效果和需求示例完全匹配:

核心OTP输入组件代码

@Composable
fun OtpInputField(
    otpLength: Int = 4,
    onOtpComplete: (String) -> Unit
) {
    // 存储OTP输入内容
    var otpValue by remember { mutableStateOf("") }
    // 控制输入框焦点
    val focusRequester = remember { FocusRequester() }
    val keyboardController = LocalSoftwareKeyboardController.current

    BasicTextField(
        value = otpValue,
        onValueChange = { newValue ->
            // 仅允许输入数字,限制最大输入长度
            if (newValue.length <= otpLength && newValue.all { it.isDigit() }) {
                otpValue = newValue
                // 输入完成后自动收起键盘触发回调
                if (newValue.length == otpLength) {
                    keyboardController?.hide()
                    onOtpComplete(newValue)
                }
            }
        },
        modifier = Modifier
            .fillMaxWidth()
            .focusRequester(focusRequester),
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.NumberPassword,
            imeAction = ImeAction.Done
        ),
        keyboardActions = KeyboardActions(
            onDone = {
                keyboardController?.hide()
                if (otpValue.length == otpLength) {
                    onOtpComplete(otpValue)
                }
            }
        ),
        // 自定义OTP格子布局,隐藏原生输入框样式
        decorationBox = {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                repeat(otpLength) { index ->
                    val isCurrentInputPos = otpValue.length == index
                    val displayChar = otpValue.getOrNull(index)?.toString() ?: ""
                    
                    Box(
                        modifier = Modifier
                            .size(48.dp)
                            .border(
                                width = if (isCurrentInputPos) 2.dp else 1.dp,
                                color = if (isCurrentInputPos) MaterialTheme.colorScheme.primary 
                                        else MaterialTheme.colorScheme.onSurfaceVariant,
                                shape = RoundedCornerShape(8.dp)
                            ),
                        contentAlignment = Alignment.Center
                    ) {
                        if (displayChar.isNotEmpty()) {
                            Text(
                                text = displayChar,
                                style = MaterialTheme.typography.headlineSmall,
                                color = MaterialTheme.colorScheme.onSurface
                            )
                        } else if (isCurrentInputPos) {
                            // 当前输入位显示闪烁光标
                            Box(
                                modifier = Modifier
                                    .width(2.dp)
                                    .height(24.dp)
                                    .background(MaterialTheme.colorScheme.primary)
                                    .animateEnterExit(
                                        enter = fadeIn(animationSpec = infiniteRepeatable(tween(500), RepeatMode.Reverse)),
                                        exit = fadeOut()
                                    )
                            )
                        }
                    }
                }
            }
        }
    )
    
    // 组件加载后自动请求焦点弹出数字键盘
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}

组件使用方法

直接在登录页对应位置调用即可:

OtpInputField(
    otpLength = 4,
    onOtpComplete = { otpCode ->
        // 此处执行OTP校验逻辑
        loginViewModel.verifyOtp(otpCode)
    }
)

可自定义调整项

  • 可修改otpLength参数适配6位等不同长度的OTP需求
  • 可自行调整OTP格子的尺寸、圆角、边框颜色、文本样式匹配设计稿
  • 原生支持系统粘贴板OTP自动填充,无需额外开发适配

内容的提问来源于stack exchange,提问作者Gautam Hazarika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 11:24:04