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()
    )
}

要执行 DoneNext 我应该添加什么代码?

使用 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)
)

文档:

有了1.0.x你就可以使用

  • keyboardOptions:包含KeyboardTypeImeAction
  • 等配置的软件键盘选项
  • 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()

KeyboardActionsonDone 中清除焦点。

电子邮件字段:

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