👁️‍🗨️

Jetpack Compose で テキストフィールドにフォーカスしたい

2022/10/06に公開

Composeでフォーカスするには?

FocusRequesterを覚えておき、フォーカスしたい時にfocusRequester.requestFocus()するだけです。

+ val focusRequester = remember { FocusRequester() }

  // フォーカスする要素を指定
  TextField(
    value = value,
    onValueChange = { value = it },
+   modifier = Modifier.focusRequester(focusRequester),
  )
  
  // フォーカスを取得したいところで
+ focusRequester.requestFocus()

エラーになることがしばしば...

これを使っていると時々こんなエラーに出くわします。が、ご丁寧に原因と対処法を示してくれています。

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

この原因はModifier.focusRequester(focusRequester)を呼んでいないことです。例えば以下のような場合に発生します。

val focusRequester = remember { FocusRequester() }

if(false){
  TextField(
    ...,
    modifier = Modifier.focusRequester(focusRequester),
  )
}
LaunchedEffect(Unit){
  focusRequester.requestFocus()
}

何がなんでもModifier.focusRequester(focusRequester)が呼ばれるように工夫しましょう。

  val focusRequester = remember { FocusRequester() }
  
  if(false){
    TextField(
      ...,
      modifier = Modifier.focusRequester(focusRequester),
    )
+   LaunchedEffect(Unit){
+     focusRequester.requestFocus()
+   }
  }
- LaunchedEffect(Unit){
-   focusRequester.requestFocus()
- }

LaunchedEffectで一番最初にフォーカスしたい時は、基本的にModifier.focusRequester(focusRequester)で指定したComposableと同じ階層で呼び出すのが良さげかなと思います!

Discussion