6

I have a screen with TextFields. I need the first TextField to be automatically focused when the screen is displayed.

Minified Example code

@Composable
fun ScreenView(
    data: ScreenViewData,
) {
    val focusManager = LocalFocusManager.current
    val focusRequester = remember {
        FocusRequester()
    }

    LaunchedEffect(
        key1 = Unit,
    ) {
        focusRequester.requestFocus()
    }

    Scaffold() { innerPadding ->
        Column {
            OutlinedTextField(
                modifier = Modifier.focusRequester(focusRequester),
            )
        }
    }
}

The code works without any issues.

But, in compose UI testing I am getting the following error.

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

Test code

@ExperimentalAnimationApi
class ScreenViewTest {

    @get:Rule
    val composeTestRule = createComposeRule()

    @ExperimentalMaterialApi
    @Test
    fun ScreenViewElementsAreDisplayed() {
        composeTestRule.setContent {
            MyAppTheme {
                ScreenView(
                    data = ScreenViewData(),
                )
            }
        }

        // Test fails before reaching assert statements
    }
}
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
Abhimanyu
  • 11,351
  • 7
  • 51
  • 121

2 Answers2

0

The SDETs on my team were running into the same issue, and we ended up resolving it by creating a function in our UI utilities module.

this is what we originally had in mind

suspend fun CoroutineScope.requestFocus(requester: FocusRequester) {
    try {
        requester.requestFocus()
    } catch (e: Exception) {
        delay(100)
        requester.requestFocus()
    }
}

but it turned out this worked as well

fun CoroutineScope.requestFocus(requester: FocusRequester) {
    requester.requestFocus()
}

I do hope the core issue gets a resolution soon, but in the meantime, maybe this can help some folks out.

Ethan
  • 179
  • 1
  • 9
0

Did you try this?:

val focusRequester = remember(data) { ... }

Milan Jurkulak
  • 557
  • 3
  • 6