Search code examples
kotlinandroid-activityandroid-jetpacklost-focus

How to fix crashes on Per App Language where D/Compose Focus: Owner FocusChanged(false) when relaunching activity in Kotlin Jetpack Compose


I am currently experimenting on Per App Language on Android(Kotlin) using Jetpack compose. I have a Drawer where the choice to change language can be invoked ( LocaleDropDownMenu from https://github.com/android/user-interface-samples/blob/main/PerAppLanguages/compose_app/app/src/main/java/com/example/perapplanguages/MainActivity.kt). I followed all what was needed and it worked, the screen(activity) will be relaunched and the text will change. However, I noticed a bug that whenever the language was changed, I see the log message "D/Compose Focus: Owner FocusChanged(false)". If after that, I try to press the Back button to exit the app, I will receive a Not Responding message. I can opt to wait, then after that if I try to press back, it will respond and close. If I do something else after changing the language, like viewing/scrolling/clicking on the Main Screen for a while, then clicking the Back button to exit, it will close without any problem

I was trying to use the FocusRequester but I think I am using it wrong. Should I use side effect?

Home Screen

@Composable
fun HomeScreen(modifier: Modifier = Modifier, viewModel: MainViewModel) {

    val focusRequester = remember { FocusRequester() }

    Box(
        modifier = Modifier
            .focusRequester(focusRequester)
            .fillMaxSize(),

        contentAlignment = Alignment.Center) {
        Column {
         ....
        }

    }


}

Logcat results:

ActivityManager   system_server     ANR in ...
                       Reason: Input dispatching timed out (Application does not have a focused window) ...
Frozen: false

Is there another way to force focus after relaunching? Or there is a way to avoid crashing the app?


Solution

  • From the code sample shared, it seems that the focusRequester is added to a Box component which isn't marked as a focusable node.

    • If you want the Box to gain focus, please add focusable() modifier
    • If this box is just a decoration and you want it to request focus and move it inside to one of its child component, then you can use a focusGroup() modifier.

    Here's the updated sample code:

    @Composable
    fun HomeScreen(modifier: Modifier = Modifier, viewModel: MainViewModel) {
    
        val focusRequester = remember { FocusRequester() }
    
        Box(
            modifier = Modifier
                .focusRequester(focusRequester)
                .fillMaxSize()
                .focusGroup() // Replace with focusable() if you want the box to gain focus
        ) {
            ...
        }
    
        LaunchedEffect(Unit) {
            focusRequester.requestFocus()
        }
    }