I have a LazyVertGrid with a bunch of Cards in it....
# compose-desktop
s
I have a LazyVertGrid with a bunch of Cards in it. I want to programmatically give focus to the first (focusable) element in the grid. However, I don't want to use a focus requester on the children themselves. Instead, I request focus on the grid and let it delegate it to its children:
Copy code
LazyVerticalGrid(Modifier.focusRequester(fr)) { .. } // somewhere else I call fr.requestFocus()
The idea is that the grid moves focus to its first child. And this works, too. I can verify that the correct item receives focus (via
onFocusChanged { print("ok!") }
) and other actions behave as expected (e.g. the Enter-key triggers a click on the element). So for all intents and purposes the correct child has focus. Except that the child is a (Material3)-Card which should change color when it receives focus, but for some reason it doesn't. There is no visual indication at all that the card has focus. What should happen is that the focused element is highlighted like in this screenshot. This highlighting works fine if I use Tab to "naturally" change focus to the element, or if I hover over the Card with the mouse. But this doesn't work if I programmatically give focus to the Grid. Is there anything to the Focus mechanism that I'm missing? I use the 1.6.0-rc1 of compose-desktop.
z
@Ralston Da Silva (note this might be a desktop-specific bug)
r
By any chance, did you happen to add a focusable() modifier to the card? The card already has a clickable within it, and that adds a focusable() modifier to it. I'm guessing you have another focusable modifier on the card which causes that focusable modifier to be focused instead of the focusable inside the card. Thanks for tagging me Zach!
s
Thanks for the response! I have no focusable() on either the card or any of its parents of children
I boiled down the UI code, and I can replicate it with this sort-of simple code
Copy code
@Composable
fun TestUi(modifier: Modifier = Modifier) {
    Column {
        val fr = remember { FocusRequester() }

        Button(
            onClick = { fr.requestFocus() }
        ) {
            Text("Press Button to Change Focus")
        }
        
        var activeItemIndex by remember { mutableStateOf<Int?>(null) }
        Text("Last/current active item was: $activeItemIndex")

        LazyVerticalGrid(
            columns = GridCells.Fixed(2),
            Modifier.focusRequester(fr),
            horizontalArrangement = Arrangement.spacedBy(16.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            items(count = 4) { index ->
                ElevatedCard(
                    onClick = { },
                    Modifier.onFocusChanged {
                        if (it.hasFocus)
                            activeItemIndex = index
                    },
                ) {
                    Text(index.toString())
                }
            }
        }
    }
}
• When you use TAB to switch between items, the cards will highlight properly as you cycle between them. • When you press the button, the focusRequester moves focus to the first card. It does receive focus, but it does not highlight.