Jetpack 撰写键盘操作侦听器 (setOnKeyListener)(SMS 的文本字段)
Jetpack compose listener for keyboard actions (setOnKeyListener) (Textfield for SMS)
我有五个 TextField。在第一个字段中输入内容后,焦点移动到下一个文本字段。
如果我在文本字段中删除了某些内容 - 焦点会移动到上一个文本字段。
所有有焦点的工作都经过 onValueChanged 部分
但是,如果文本字段中的值为空白 ("") - 如果我在键盘上按退格键,onValueChanged 没有任何反应,因为字段中的值未更改。我需要以某种方式将焦点放在以前的文本字段
那么我如何在撰写中的文本字段的软键盘中使用监听器进行后退?
我试过使用 KeyboardActions,
keyboardActions = KeyboardActions(
onPrevious = {
//some work with foucs
},
),
但它不起作用
第二个问题:
如果文本字段被点击(或获得焦点)如何在结束文本的字段中设置光标?
我需要即使用户点击字符串中间的光标设置结束。
有解决方案@nglauber
输入短信的文本字段(目前):
@Composable
fun SMSTextFields(
modifier: Modifier,
smsCodeLength: Int = 5,
whenFull: (smsCode: String) -> Unit
) {
val enteredNumbers = remember {
mutableStateListOf(
*((0 until smsCodeLength).map { "" }.toTypedArray())
)
}
val focusRequesters: List<FocusRequester> = remember {
(0 until smsCodeLength).map { FocusRequester() }
}
Row(modifier = modifier.padding(start = 60.dp, end = 60.dp)) {
(0 until smsCodeLength).forEach { index ->
TextField(
modifier = Modifier
.weight(1f)
.size(120.dp, 80.dp)
.onKeyEvent { event ->
val cellValue = enteredNumbers[index]
if (event.type == KeyEventType.KeyUp) {
if (event.key == Key.Backspace && cellValue == "") {
focusRequesters
.getOrNull(index - 1)
?.requestFocus()
enteredNumbers[index - 1] = ""
} else if (cellValue != "") {
focusRequesters
.getOrNull(index + 1)
?.requestFocus()
}
}
false
}
.padding(vertical = 2.dp)
.focusOrder(focusRequesters[index])
.focusRequester(focusRequesters[index]),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = whiteBackground,
unfocusedIndicatorColor = greyColor,
focusedIndicatorColor = signUpColorButton,
cursorColor = greyColor,
textColor = greyColor
),
textStyle = smsCodeEnterStyle,
singleLine = true,
value = enteredNumbers[index],
onValueChange = { value: String ->
if (value.isDigitsOnly()) {
if (value.length > 1) {
enteredNumbers[index] = value.last().toString()
return@TextField
}
if (focusRequesters[index].freeFocus()) {
enteredNumbers[index] = value
if (enteredNumbers[index].isBlank() && index > 0 && index <5) {
focusRequesters[index - 1].requestFocus()
} else if (index < smsCodeLength - 1) {
focusRequesters[index + 1].requestFocus()
}
else if (enteredNumbers.size == 5){
whenFull(enteredNumbers.joinToString(separator = ""))
}
}
}
},
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
)
Spacer(modifier = Modifier.width(4.dp))
}
}
}
@ExperimentalComposeUiApi
@Composable
fun EnterOtpView() {
val scrollState = rememberScrollState()
val focusManager = LocalFocusManager.current
val digits = remember {
mutableStateListOf(
*((0 until 4).map { "" }.toTypedArray())
)
}
val focusRequesters: List<FocusRequester> = remember {
(0 until 4).map { FocusRequester() }
}
Column(
Modifier.padding(horizontal = 70.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = "123 456 8550", style = MaterialTheme.typography.h3, color = Purple,
modifier = Modifier.padding(top = 20.dp, bottom = 30.dp)
)
Row(
modifier = Modifier
.fillMaxWidth(1f)
.wrapContentHeight(),
Arrangement.SpaceBetween,
Alignment.CenterVertically
) {
(0 until 4).forEach { index ->
TextField(
modifier = Modifier
.weight(0.2f)
.padding(end = 4.dp)
.onKeyEvent {
if (it.nativeKeyEvent.keyCode == 67) {
if (digits[index].isEmpty()) {
focusManager.moveFocus(FocusDirection.Left)
}
digits[index] = ""
}
true
}
.padding(vertical = 2.dp)
.focusOrder(focusRequesters[index])
.focusRequester(focusRequesters[index]),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent
),
singleLine = true,
textStyle = MaterialTheme.typography.body1.copy(textAlign = TextAlign.Center),
value = digits[index],
onValueChange = {
if (digits[index].isEmpty() && it.isDigitsOnly()) {
digits[index] = it
focusManager.moveFocus(FocusDirection.Right)
}
},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next,
keyboardType = KeyboardType.Number
),
keyboardActions = KeyboardActions(
onNext = {
focusManager.moveFocus(FocusDirection.Right)
}
)
)
}
}
}}
使用 nativeKeyEvent 和 focusManager 为我工作。
我有五个 TextField。在第一个字段中输入内容后,焦点移动到下一个文本字段。 如果我在文本字段中删除了某些内容 - 焦点会移动到上一个文本字段。 所有有焦点的工作都经过 onValueChanged 部分
但是,如果文本字段中的值为空白 ("") - 如果我在键盘上按退格键,onValueChanged 没有任何反应,因为字段中的值未更改。我需要以某种方式将焦点放在以前的文本字段
那么我如何在撰写中的文本字段的软键盘中使用监听器进行后退?
我试过使用 KeyboardActions,
keyboardActions = KeyboardActions(
onPrevious = {
//some work with foucs
},
),
但它不起作用
第二个问题:
如果文本字段被点击(或获得焦点)如何在结束文本的字段中设置光标?
我需要即使用户点击字符串中间的光标设置结束。
有解决方案@nglauber 输入短信的文本字段(目前):
@Composable
fun SMSTextFields(
modifier: Modifier,
smsCodeLength: Int = 5,
whenFull: (smsCode: String) -> Unit
) {
val enteredNumbers = remember {
mutableStateListOf(
*((0 until smsCodeLength).map { "" }.toTypedArray())
)
}
val focusRequesters: List<FocusRequester> = remember {
(0 until smsCodeLength).map { FocusRequester() }
}
Row(modifier = modifier.padding(start = 60.dp, end = 60.dp)) {
(0 until smsCodeLength).forEach { index ->
TextField(
modifier = Modifier
.weight(1f)
.size(120.dp, 80.dp)
.onKeyEvent { event ->
val cellValue = enteredNumbers[index]
if (event.type == KeyEventType.KeyUp) {
if (event.key == Key.Backspace && cellValue == "") {
focusRequesters
.getOrNull(index - 1)
?.requestFocus()
enteredNumbers[index - 1] = ""
} else if (cellValue != "") {
focusRequesters
.getOrNull(index + 1)
?.requestFocus()
}
}
false
}
.padding(vertical = 2.dp)
.focusOrder(focusRequesters[index])
.focusRequester(focusRequesters[index]),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = whiteBackground,
unfocusedIndicatorColor = greyColor,
focusedIndicatorColor = signUpColorButton,
cursorColor = greyColor,
textColor = greyColor
),
textStyle = smsCodeEnterStyle,
singleLine = true,
value = enteredNumbers[index],
onValueChange = { value: String ->
if (value.isDigitsOnly()) {
if (value.length > 1) {
enteredNumbers[index] = value.last().toString()
return@TextField
}
if (focusRequesters[index].freeFocus()) {
enteredNumbers[index] = value
if (enteredNumbers[index].isBlank() && index > 0 && index <5) {
focusRequesters[index - 1].requestFocus()
} else if (index < smsCodeLength - 1) {
focusRequesters[index + 1].requestFocus()
}
else if (enteredNumbers.size == 5){
whenFull(enteredNumbers.joinToString(separator = ""))
}
}
}
},
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
)
Spacer(modifier = Modifier.width(4.dp))
}
}
}
@ExperimentalComposeUiApi
@Composable
fun EnterOtpView() {
val scrollState = rememberScrollState()
val focusManager = LocalFocusManager.current
val digits = remember {
mutableStateListOf(
*((0 until 4).map { "" }.toTypedArray())
)
}
val focusRequesters: List<FocusRequester> = remember {
(0 until 4).map { FocusRequester() }
}
Column(
Modifier.padding(horizontal = 70.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = "123 456 8550", style = MaterialTheme.typography.h3, color = Purple,
modifier = Modifier.padding(top = 20.dp, bottom = 30.dp)
)
Row(
modifier = Modifier
.fillMaxWidth(1f)
.wrapContentHeight(),
Arrangement.SpaceBetween,
Alignment.CenterVertically
) {
(0 until 4).forEach { index ->
TextField(
modifier = Modifier
.weight(0.2f)
.padding(end = 4.dp)
.onKeyEvent {
if (it.nativeKeyEvent.keyCode == 67) {
if (digits[index].isEmpty()) {
focusManager.moveFocus(FocusDirection.Left)
}
digits[index] = ""
}
true
}
.padding(vertical = 2.dp)
.focusOrder(focusRequesters[index])
.focusRequester(focusRequesters[index]),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent
),
singleLine = true,
textStyle = MaterialTheme.typography.body1.copy(textAlign = TextAlign.Center),
value = digits[index],
onValueChange = {
if (digits[index].isEmpty() && it.isDigitsOnly()) {
digits[index] = it
focusManager.moveFocus(FocusDirection.Right)
}
},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next,
keyboardType = KeyboardType.Number
),
keyboardActions = KeyboardActions(
onNext = {
focusManager.moveFocus(FocusDirection.Right)
}
)
)
}
}
}}
使用 nativeKeyEvent 和 focusManager 为我工作。