Fried Rice
Fried Rice

Reputation: 3733

Manually move accessibility focus in Jetpack Compose

With Android View, I'm able to move the focus to a View like so:

fun View.requestAccessibilityFocus() {
    requestFocus()
    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}

How do I achieve this in Jetpack Compose?

I tried using FocusRequester but it doesn't seem to do anything:

val lifecycleOwner = LocalLifecycleOwner.current
val requester = FocusRequester()

Box {
    ...
    Image(
        ...
        contentDescription = "My heading",
        modifier = Modifier
            ...
            .focusRequester(requester)
    )
}

DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
         if (event == Lifecycle.Event.ON_RESUME) {
             requester.requestFocus()
         }
    }
    lifecycleOwner.lifecycle.addObserver(observer)
    onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}

Upvotes: 9

Views: 5912

Answers (2)

Fried Rice
Fried Rice

Reputation: 3733

I had to add .focusable() and must do so after .focusRequester(focusRequester).

Box {
    ...
    Image(
        ...
        contentDescription = "My heading",
        modifier = Modifier
            ...
            .focusRequester(requester)
            .focusable()
    )
}

Upvotes: 6

Nikhil Dupally
Nikhil Dupally

Reputation: 973

This happens because DiposableEffect might be calling during recomposition. You should not request focus during composition. The solution I have found is to request a focus right after the composition. Like this

LaunchedEffect(Unit) {
        this.coroutineContext.job.invokeOnCompletion {
            focusRequester.requestFocus()
        }
    }

This makes sure your code will run when the LauchedEffect leaves the composition because it(the coroutine) either got canceled or completed.

Upvotes: 3

Related Questions