Jetpack 撰写:设置 ImeAction 不会关闭或更改键盘焦点
Jetpack compose: Setting ImeAction does not close or change focus for the keyboard
我正在使用 Jetpack compose 1.0.0-alpha07
。我制作了一个登录屏幕,其中包含两个使用其他可组合项自定义的 TextField
。
但是,在keyboardOptions
中设置ImeAction
似乎不起作用。例如 ImeAction.Next
不会将焦点移动到下一个 TextField。我想我应该做点什么让它成为可能,但是没有文档或文章甚至简短地谈论过 ImeOptions
。这是我的屏幕代码:
登录 可组合:
EmailEdit(onChange = { email.value = it })
PasswordEdit(onChange = { password.value = it })
电子邮件编辑:
@Composable
fun EmailEdit(onChange: (String) -> Unit) {
val t = remember { mutableStateOf("") }
TextField(
value = t.value,
onValueChange = { value ->
t.value = value
onChange(value)
},
leadingIcon = { Icon(asset = Icons.Default.Email) },
label = { Text(text = "Email") },
maxLines = 1,
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next, // ** Go to next **
keyboardType = KeyboardType.Email
),
visualTransformation = VisualTransformation.None
)
} errorHint = "Not a valid email"
)
}
通过编辑:
@Composable
fun PasswordEdit(onChange: (String) -> Unit) {
val t = remember { mutableStateOf("") }
TextField(
value = t.value,
onValueChange = { value ->
t.value = value
onChange(value)
},
leadingIcon = { Icon(asset = Icons.Default.Security) },
label = { Text(text = "Password") },
maxLines = 1,
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done, // ** Done. Close the keyboard **
keyboardType = KeyboardType.Text
),
visualTransformation = PasswordVisualTransformation()
)
}
要执行 Done
和 Next
我应该添加什么代码?
使用 onImeActionPerformed
参数。
对于Done
:
TextField(
onImeActionPerformed = { _, controller ->
controller?.hideSoftwareKeyboard()
}
)
对于Next
:
val focusRequester = remember { FocusRequester() }
TextField(
onImeActionPerformed = { _, _ ->
focusRequester.requestFocus()
}
)
TextField(
modifier = Mofifier.focusRequester(focusRequester)
)
这是一个工作示例:
val focusRequester = remember { FocusRequester() }
val email = remember { mutableStateOf("") }
TextField(
value = email.value,
onValueChange = { email.value = it },
imeAction = ImeAction.Next,
onImeActionPerformed = { _, _ -> focusRequester.requestFocus() }
)
val password = remember { mutableStateOf("") }
TextField(
value = password.value,
onValueChange = { password.value = it },
imeAction = ImeAction.Done,
onImeActionPerformed = { _, controller -> controller?.hideSoftwareKeyboard() },
modifier = Modifier.focusRequester(focusRequester)
)
文档:
- FocusRequestModifier:https://developer.android.com/reference/kotlin/androidx/compose/ui/FocusRequesterModifier
- 文本字段:https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#TextField(kotlin.String,%20kotlin.Function1,%20androidx.compose.ui.Modifier,%20androidx.compose.ui.text.TextStyle,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Boolean,%20androidx.compose.ui.text.input.VisualTransformation,%20androidx.compose.foundation.text.KeyboardOptions,%20kotlin.Int,%20kotlin.Function2,%20kotlin.Function1,%20androidx.compose.foundation.InteractionState,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Shape)
有了1.0.x
你就可以使用
keyboardOptions
:包含KeyboardType
和ImeAction
等配置的软件键盘选项
keyboardActions
当输入服务发出输入法操作时,会调用相应的回调
对于Done
:
您可以使用 LocalSoftwareKeyboardController
与键盘进行交互。
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = {keyboardController?.hide()}
)
对于Next
:
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(
onNext = { focusRequester.requestFocus() }
)
类似于:
val (focusRequester) = FocusRequester.createRefs()
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
value = text,
onValueChange = {
text = it
},
label = { Text("Label") },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(
onNext = { focusRequester.requestFocus() }
)
)
TextField(
value = text,
onValueChange = {
text = it
},
modifier = Modifier.focusRequester(focusRequester),
label = { Text("Label") },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = { keyboardController?.hide() }
)
)
在这种情况下使用 Compose,您需要创建一组对屏幕上每个可聚焦文本字段的引用,如下所示(textField1、textField2)并获取对 keyboardController 的引用。
然后您可以向键盘选项添加一种操作,指示操作按钮在显示键盘时的外观。
在 keyboardActions 参数中,您可以针对指定的 IME 操作调用函数 - 在这种情况下,我已经声明我希望 textField2 在按下键盘操作按钮时获得焦点。您在 TextField 的 Modifier.focusRequester 参数中分配引用。
最后,为了让您的第一个 TextField 在屏幕出现时获得焦点,您可以调用 DisposableEffect 函数,在该函数中指定您希望 textField1 在屏幕首次显示时获得焦点。
val (textField1, textField2) = remember { FocusRequester.createRefs() }
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
modifier = Modifier.focusRequester(textField1),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions( onNext = {textField2.requestFocus()}
),
)
TextField(
modifier = Modifier.focusRequester(textField2),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions( onDone = {
keyboardController?.hide()}
),
)
DisposableEffect(Unit) {
textField1.requestFocus()
onDispose { }
}
您可以使用 LocalFocusManager。
val localFocusManager = LocalFocusManager.current
在您的字段的父级可组合项中。
要将焦点移至下一个字段:
localFocusManager.moveFocus(FocusDirection.Down)
在 KeyboardActions 的 onNext 内部将焦点移动到特定方向,例如左、右、上、下。
要清除焦点:
localFocusManager.clearFocus()
在 KeyboardActions 的 onDone 中清除焦点。
电子邮件字段:
OutlinedTextField(
value = userId,
onValueChange = { userId = it },
label = { Text("Email") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_account),
contentDescription = "ID"
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Gray,
unfocusedBorderColor = Color.LightGray,
focusedLabelColor = Color(0xffcc0000)
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(onNext = {
localFocusManager.moveFocus(FocusDirection.Down)
})
)
密码字段:
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_password),
contentDescription = "Password"
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Gray,
unfocusedBorderColor = Color.LightGray,
focusedLabelColor = Color(0xffcc0000)
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
localFocusManager.clearFocus()
})
)
尝试使用版本 1.0.1
我正在使用 Jetpack compose 1.0.0-alpha07
。我制作了一个登录屏幕,其中包含两个使用其他可组合项自定义的 TextField
。
但是,在keyboardOptions
中设置ImeAction
似乎不起作用。例如 ImeAction.Next
不会将焦点移动到下一个 TextField。我想我应该做点什么让它成为可能,但是没有文档或文章甚至简短地谈论过 ImeOptions
。这是我的屏幕代码:
登录 可组合:
EmailEdit(onChange = { email.value = it })
PasswordEdit(onChange = { password.value = it })
电子邮件编辑:
@Composable
fun EmailEdit(onChange: (String) -> Unit) {
val t = remember { mutableStateOf("") }
TextField(
value = t.value,
onValueChange = { value ->
t.value = value
onChange(value)
},
leadingIcon = { Icon(asset = Icons.Default.Email) },
label = { Text(text = "Email") },
maxLines = 1,
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Next, // ** Go to next **
keyboardType = KeyboardType.Email
),
visualTransformation = VisualTransformation.None
)
} errorHint = "Not a valid email"
)
}
通过编辑:
@Composable
fun PasswordEdit(onChange: (String) -> Unit) {
val t = remember { mutableStateOf("") }
TextField(
value = t.value,
onValueChange = { value ->
t.value = value
onChange(value)
},
leadingIcon = { Icon(asset = Icons.Default.Security) },
label = { Text(text = "Password") },
maxLines = 1,
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done, // ** Done. Close the keyboard **
keyboardType = KeyboardType.Text
),
visualTransformation = PasswordVisualTransformation()
)
}
要执行 Done
和 Next
我应该添加什么代码?
使用 onImeActionPerformed
参数。
对于Done
:
TextField(
onImeActionPerformed = { _, controller ->
controller?.hideSoftwareKeyboard()
}
)
对于Next
:
val focusRequester = remember { FocusRequester() }
TextField(
onImeActionPerformed = { _, _ ->
focusRequester.requestFocus()
}
)
TextField(
modifier = Mofifier.focusRequester(focusRequester)
)
这是一个工作示例:
val focusRequester = remember { FocusRequester() }
val email = remember { mutableStateOf("") }
TextField(
value = email.value,
onValueChange = { email.value = it },
imeAction = ImeAction.Next,
onImeActionPerformed = { _, _ -> focusRequester.requestFocus() }
)
val password = remember { mutableStateOf("") }
TextField(
value = password.value,
onValueChange = { password.value = it },
imeAction = ImeAction.Done,
onImeActionPerformed = { _, controller -> controller?.hideSoftwareKeyboard() },
modifier = Modifier.focusRequester(focusRequester)
)
文档:
- FocusRequestModifier:https://developer.android.com/reference/kotlin/androidx/compose/ui/FocusRequesterModifier
- 文本字段:https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#TextField(kotlin.String,%20kotlin.Function1,%20androidx.compose.ui.Modifier,%20androidx.compose.ui.text.TextStyle,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Function0,%20kotlin.Boolean,%20androidx.compose.ui.text.input.VisualTransformation,%20androidx.compose.foundation.text.KeyboardOptions,%20kotlin.Int,%20kotlin.Function2,%20kotlin.Function1,%20androidx.compose.foundation.InteractionState,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Color,%20androidx.compose.ui.graphics.Shape)
有了1.0.x
你就可以使用
keyboardOptions
:包含KeyboardType
和ImeAction
等配置的软件键盘选项
keyboardActions
当输入服务发出输入法操作时,会调用相应的回调
对于Done
:
您可以使用 LocalSoftwareKeyboardController
与键盘进行交互。
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = {keyboardController?.hide()}
)
对于Next
:
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(
onNext = { focusRequester.requestFocus() }
)
类似于:
val (focusRequester) = FocusRequester.createRefs()
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
value = text,
onValueChange = {
text = it
},
label = { Text("Label") },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(
onNext = { focusRequester.requestFocus() }
)
)
TextField(
value = text,
onValueChange = {
text = it
},
modifier = Modifier.focusRequester(focusRequester),
label = { Text("Label") },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = { keyboardController?.hide() }
)
)
在这种情况下使用 Compose,您需要创建一组对屏幕上每个可聚焦文本字段的引用,如下所示(textField1、textField2)并获取对 keyboardController 的引用。
然后您可以向键盘选项添加一种操作,指示操作按钮在显示键盘时的外观。
在 keyboardActions 参数中,您可以针对指定的 IME 操作调用函数 - 在这种情况下,我已经声明我希望 textField2 在按下键盘操作按钮时获得焦点。您在 TextField 的 Modifier.focusRequester 参数中分配引用。
最后,为了让您的第一个 TextField 在屏幕出现时获得焦点,您可以调用 DisposableEffect 函数,在该函数中指定您希望 textField1 在屏幕首次显示时获得焦点。
val (textField1, textField2) = remember { FocusRequester.createRefs() }
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
modifier = Modifier.focusRequester(textField1),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions( onNext = {textField2.requestFocus()}
),
)
TextField(
modifier = Modifier.focusRequester(textField2),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions( onDone = {
keyboardController?.hide()}
),
)
DisposableEffect(Unit) {
textField1.requestFocus()
onDispose { }
}
您可以使用 LocalFocusManager。
val localFocusManager = LocalFocusManager.current
在您的字段的父级可组合项中。
要将焦点移至下一个字段:
localFocusManager.moveFocus(FocusDirection.Down)
在 KeyboardActions 的 onNext 内部将焦点移动到特定方向,例如左、右、上、下。
要清除焦点:
localFocusManager.clearFocus()
在 KeyboardActions 的 onDone 中清除焦点。
电子邮件字段:
OutlinedTextField(
value = userId,
onValueChange = { userId = it },
label = { Text("Email") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_account),
contentDescription = "ID"
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Gray,
unfocusedBorderColor = Color.LightGray,
focusedLabelColor = Color(0xffcc0000)
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(onNext = {
localFocusManager.moveFocus(FocusDirection.Down)
})
)
密码字段:
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_password),
contentDescription = "Password"
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Gray,
unfocusedBorderColor = Color.LightGray,
focusedLabelColor = Color(0xffcc0000)
),
keyboardOptions =
KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
localFocusManager.clearFocus()
})
)
尝试使用版本 1.0.1