Farhazul Mullick
12/06/2023, 4:09 PMModifier.onKeyEvent { keyEvent ->
Napier.d(tag = "OTPVerification") { "Keyboard button clicked ${keyEvent.key}" }
if (keyEvent.type == KeyEventType.KeyUp && keyEvent.key == Key.Backspace) {
// code...
}
true
}
Alexander Maryanovsky
12/06/2023, 7:14 PMAlexander Maryanovsky
12/06/2023, 7:20 PMFarhazul Mullick
12/07/2023, 4:44 AMFarhazul Mullick
12/07/2023, 4:46 AMMofe Ejegi
02/16/2024, 5:56 PMFarhazul Mullick
02/17/2024, 12:48 PMMofe Ejegi
02/17/2024, 6:41 PMFarhazul Mullick
02/19/2024, 12:51 PMMofe Ejegi
02/19/2024, 12:54 PMAlexander Maryanovsky
02/19/2024, 12:56 PMonPreviewKeyEvent
also doesn’t work?Mofe Ejegi
02/19/2024, 12:57 PMFarhazul Mullick
02/19/2024, 1:05 PMFarhazul Mullick
02/19/2024, 1:07 PMMofe Ejegi
02/19/2024, 1:08 PMFarhazul Mullick
02/19/2024, 1:18 PM@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun OTPInputField(
modifier: Modifier = Modifier,
otpText: String,
maxOTPCount: Int = 6,
isError: Boolean = false,
errorMsg: String = String.EMPTY,
onOtpTextChange: (String) -> Unit,
onOTPFilled: (String) -> Unit
) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
Column {
BasicTextField(
value = TextFieldValue(otpText, selection = TextRange(otpText.length)),
onValueChange = {textField ->
if (textField.text.length <= maxOTPCount) {
val otpFilled: Boolean = textField.text.length == maxOTPCount
Napier.d { "Line68: onValueChange, text: ${textField.text}" }
onOtpTextChange.invoke(textField.text)
if (otpFilled) {
onOTPFilled.invoke(textField.text)
}
}
},
decorationBox = {
Row(
horizontalArrangement = Arrangement.Center,
) {
repeat(maxOTPCount) { index ->
val char = when {
index >= otpText.length -> ""
else -> otpText[index].toString()
}
val check1: Boolean = char.isEmpty() && index == otpText.length
val filledBox: Boolean = index < otpText.length
var check2: Boolean by remember { mutableStateOf(false) }
LaunchedEffect(key1 = check2) {
delay(500)
check2 = !check2
}
Box(contentAlignment = Alignment.Center) {
Text(
modifier = Modifier
.size(54.dp)
.border(
width = 1.dp,
color = if (isError) LocalThemeColors.current.errorColors.error_500
else if (filledBox) LocalThemeColors.current.primaryColor.primary_500
else LocalThemeColors.current.greyPaletteColors.grey_300,
shape = RoundedCornerShape(8.dp)
)
.padding(vertical = 13.dp),
text = char,
textAlign = TextAlign.Center,
style = LocalTextStyles.current.H3Bold
)
if (check1 and check2) {
Box(
modifier = Modifier.width(2.dp)
.height(LocalDimensions.current.dp20)
.background(color = LocalThemeColors.current.greyPaletteColors.grey_900)
)
}
}
HSpacer(LocalDimensions.current.dp8)
}
}
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
keyboardController?.hide()
focusManager.clearFocus()
}
),
singleLine = true
)
if (isError) ErrorIconLabel(errorText = errorMsg)
}
}
Farhazul Mullick
02/19/2024, 1:19 PM// Four digit OTP-BOX
var otpText: String by remember { mutableStateOf(String.EMPTY) }
OTPInputField(
otpText = otpText,
maxOTPCount = 4,
onOtpTextChange = {newOTP: String ->
otpText = newOTP
},
isError = isError,
errorMsg = errorText,
onOTPFilled = {otp: String ->
// otp string is complete otp.
// callback trigurred when all boxes are filled.
}
)
Mofe Ejegi
02/19/2024, 1:33 PM