https://kotlinlang.org logo
Title
a

Alexander Maryanovsky

02/28/2022, 1:56 PM
It seems
Modifier.focusable(false)
doesn’t work on buttons. I took the first focus example from https://github.com/JetBrains/compose-jb/tree/master/tutorials/Tab_Navigation and added a button at the bottom:
TextButton(
    onClick = { println("Clicked") },
    modifier = Modifier.focusable(false)
){
    Text("Click me")
}
and the button still participates in focus navigation, and when it has focus and I press ENTER, it prints “Clicked”. Is it a bug or am I misunderstanding what
focusable(false)
should do?
r

Ralston Da Silva

03/24/2022, 5:43 PM
Sorry for the late response. What are you trying to do? Are you trying to prevent the Button from being focusable when you navigate using a keyboard? The clickable inside button has it's own focus modifier, and it is focusable only in non-touch mode. If you want to exclude the button from focus search, you can use the canFocus property
TextButton(
    onClick = { println("Clicked") },
    modifier = Modifier.focusProperties { canFocus = false }
){
    Text("Click me")
}
a

Alexander Maryanovsky

03/24/2022, 6:31 PM
I’m trying to achieve two things (separately, if possible): 1. Remove the button from tab-navigation. 2. Make it not respond to keyboard events (pressing ENTER) after it’s clicked (and presumably receives focus)
From your reply I understand
Modifier.focusProperties{ canFocus = false }
does 1
If so, I have to say
Modifier.focusable(enabled: Boolean)
is very confusing.
r

Ralston Da Silva

03/24/2022, 8:09 PM
I think the sample addresses both 1 and 2. Modifier.focusable can be used to make something focusable (you can navigate to it using a DPad). Setting enabled=false will remove the focus modifier from composition. Modifier.clickable can be used to make something clickable (It internally makes the item focusable only in non-touch mode, so clicking on it does not give it focus, but navigating to it with a DPad gives it focus). So if you use clickable you don't have to think about focus. Clickable has an enabled parameter too, setting it to false will propagate that parameter to the focusable within it. In your example, you could set the enabled parameter on TextButton. This will be propagated all the way down to the focus modifier inside the button. But in your specific usecase you need the clickable functionality of TextButton, but not the focus portions. We don't provide a way to do this because we want users that use the button to automatically get focus navigation, accessibility semantics, etc. For situations like these we usually suggest that users build their own custom button using the lower APIs - In ths case maybe you don't need something that is clickable, but you need something that just responds to touch gestures. That said, in this case there happens to be a way to disable focus. if you use
Modifier.focusProperties { canFocus = false }
the item will not be focusable, and thus would not respond to any key events. Even though this is a solution for your usecase, I feel that it would be better to not use TextButton, but build your own custom component instead. It would allow you to customize the accessibility behavior of your component.