请求在 jetpack compose 中关注 TextField

Muk*_*gir 7 android kotlin android-jetpack-compose

如何在 jetpack compose 中自动关注文本字段。当我单击文本字段并开始在其上键入时。同时,当我单击后退按钮时,然后当我尝试单击文本字段时,没有任何反应。

val textState = remember { mutableStateOf(TextFieldValue()) }
TextField(
    modifier = Modifier.fillMaxWidth(),
    value = textState.value,
    onValueChange = { value : TextFieldValue ->
        textState.value = value
    }
)
Run Code Online (Sandbox Code Playgroud)

Gab*_*tti 41

您可以将其FocusRequester与 SideEffect 一起使用。
就像是:

var text by remember { mutableStateOf("text") }

// initialize focus reference to be able to request focus programmatically
val focusRequester = FocusRequester()

Column {
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        label = { Text("label") },
        modifier = Modifier
            // add focusRequester modifier 
            .focusRequester(focusRequester)
    )
Run Code Online (Sandbox Code Playgroud)

然后使用focusRequester.requestFocus(). 通过这种方式,系统将焦点授予与 this 相关的组件FocusRequester

要在屏幕出现时自动聚焦该字段,您可以使用:

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}
Run Code Online (Sandbox Code Playgroud)

要手动将焦点授予该字段:

    Button(
         onClick = { focusRequester.requestFocus() }
    ){
        Text("Click to give the focus")
    }
Run Code Online (Sandbox Code Playgroud)

  • 在自动对焦领域中使用“DisposableEffect”比“LaunchedEffect”有什么优势? (10认同)
  • @SvenJacobs是的,这种情况不仅发生在“LaucnhedEffect”中,而且也发生在“DisposableEffect”中。你不应该在构图过程中要求焦点。我找到的解决方案是在构图后立即请求焦点。因此,您将执行 ```LaunchedEffect(Unit) { this.coroutineContext.job.invokeOnCompletion { focusRequester.requestFocus() } }``` 这可确保您的代码在 ```LauchedEffect``` 离开组合时运行因为它(协程)要么被取消,要么完成。 (9认同)
  • DisposableEffect 用于仅请求一次焦点,但它没有任何意义,因为我们不使用 onDispose。所以我认为使用 LaunchedEffect(Unit){} 更有意义,因为它只会启动一次,第一次创建组合,并且不会请求重点关注重组。 (5认同)

hol*_*ium 18

在最新版本的 Jetpack Compose(目前为 1.3.3)中,如果您使用以下命令:

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}
Run Code Online (Sandbox Code Playgroud)

尝试自动对焦 a TextField,您会得到:

java.lang.IllegalStateException:
FocusRequester is not initialized. Here are some possible fixes:

    1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
    2. Did you forget to add a Modifier.focusRequester() ?
    3. Are you attempting to request focus during composition? Focus requests should be made in
    response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
Run Code Online (Sandbox Code Playgroud)

这是一个不使用的优雅解决方案delay

java.lang.IllegalStateException:
FocusRequester is not initialized. Here are some possible fixes:

    1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
    2. Did you forget to add a Modifier.focusRequester() ?
    3. Are you attempting to request focus during composition? Focus requests should be made in
    response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
Run Code Online (Sandbox Code Playgroud)

  • 我尝试了很多方法来请求焦点,这是唯一有效的方法!许多与焦点相关的函数似乎已经在 J​​etpack Compose 中被弃用,但这些函数还没有被弃用。这甚至适用于像“Text()”这样不可聚焦的组件,只需在“.focusRequester(focusRequester)”之后添加“.focusable()”,这些函数的顺序很重要! (3认同)
  • @Tonnie 在“onGloballyPositioned”中使用“requestFocus”会导致循环重组,并且您可以无限地获得焦点。使用“LaunchedEffect”方法代替 (2认同)

小智 15

val focusRequester = remember { FocusRequester() }
val inputService = LocalTextInputService.current
val focus = remember { mutableStateOf(false) }
BasicTextField(
    value = "value",
    modifier = Modifier
        .height(40.dp)
        .fillMaxWidth()
        .focusRequester(focusRequester)
        .onFocusChanged {
            if (focus.value != it.isFocused) {
                focus.value = it.isFocused
                if (!it.isFocused) {
                    inputService?.hideSoftwareKeyboard()
                }
            }
        },
),

LaunchedEffect("") {
    delay(300)
    inputService?.showSoftwareKeyboard()
    focusRequester.requestFocus()
}
Run Code Online (Sandbox Code Playgroud)

  • 请在您的回答中提供更多详细信息。正如目前所写的,很难理解您的解决方案。 (3认同)

小智 14

发布问题的更新答案(API 在 Compose Beta 中重命名)

@Composable
fun AutoFocusingText() {
    var value by mutableStateOf("Enter Text")
    val focusRequester = remember { FocusRequester() }
    TextField(
        value = value, 
        onValueChange = { value = it },
        modifier = Modifier.focusRequester(focusRequester)
    )
    
    DisposableEffect(Unit) {
        focusRequester.requestFocus()
        onDispose { }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可行,但将光标设置在单词的开头。当请求焦点时,如何将光标设置在单词末尾? (6认同)
  • @CharlesWoodson,您需要在“TextField”的值中使用“TextFieldValue”。您可以在“TextFieldValue”中设置选择 (3认同)
  • @CharlesWoodson 如果您仍然希望将光标设置到文本字段中字符串的末尾,那么您可以这样做 val textFieldValue = remember { mutableStateOf( TextFieldValue(someString, TextRange(someString.length)) ) 设置值TextField 的 textFieldValue.value 像这样 TextField( value = textFieldValue.value ) 这将使文本字段预先填充 someString 并且光标位置将是字符串末尾的 someString 的长度。 (2认同)

Ben*_*yam 7

如果您希望在导航到屏幕时文本字段自动聚焦,则可以使用此功能。这允许您在构图过程中不要做requestFocus这不是您应该做的事情。否则,您有时会收到IllegalStateException“FocusRequester 未初始化”消息。

 @Composable fun YourComposable(){ 
   val focusRequester = remember {FocusRequester()}
    
        LaunchedEffect(Unit) {
            this.coroutineContext.job.invokeOnCompletion {
                focusRequester.requestFocus()
            }
        }
    
       OutlinedTextField( modifier = Modifier.focusRequester(focusRequester))
         
              
}
Run Code Online (Sandbox Code Playgroud)

这是因为当离开组合LaucnhedEffeect时里面的协程会被取消。LaunchedEffect


2ja*_*222 5

取自 Compose Unit Tests 并应用于 TextField Link

    @ExperimentalFocus
    @Composable
    fun AutoFocusingText() {
        val textState = remember { mutableStateOf(TextFieldValue()) }
        val focusState = remember { mutableStateOf(FocusState.Inactive) }
        val focusRequester = FocusRequester()
        val focusModifier = Modifier.focus()
        Row(
            modifier = Modifier.focusObserver { focusState.value = it }
        ) {
            val focusRequesterModifier = Modifier.focusRequester(focusRequester)
            TextField(
                modifier = focusModifier.then(focusRequesterModifier),
                value = textState.value,
                onValueChange = { value: TextFieldValue ->
                    textState.value = value
                },

                )
        }
        onActive {
            focusRequester.requestFocus()
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑:将 Box 更改为 Row 因为 Box 已在 '1.0.0-alpha04' 中被弃用