https://kotlinlang.org logo
#compose
Title
# compose
m

Mikołaj Kąkol

10/26/2021, 5:20 AM
How in compose we should pass different states of UI (selected/checked/focued/enabled/etc)? In views we had all those state_xxx in xml. It’s bit cumbersome to pass all those states as params to function. I was wondering if few
CompositionLocalPressed/Enabled
would be a good idea? My main problem is how to change font color based on those states and I’m bit lazy to pass it to each function.
m

maciejciemiega

10/26/2021, 7:30 AM
I think the idea is to tailor it to your needs. Not every control can be disabled, pressed, checked, focused so some of these states would not apply to every component. Also you don't have to pass all the colors separately. You can bundle them like e.g. in
Checkbox
with
CheckboxColors
. Text already reacts LocalContentColor and LocalContentAlpha so you can use these two to control the text based on all your defined states. Or just pass different
color
or
style
to it, if you have direct access to
Text
call. Of course all this color calculation based on state can be done once e.g. by creating your custom Text composable if that would make you easier for you.
m

matvei

10/26/2021, 9:23 AM
There's an API called
InteractionSource
that every clickable/toggleable/checkable widget accepts as a parameter. You can create such state yourself and own it, calling
val pressed = interactionSournce.collectAsPressed()
to know whether item is pressed/hovered/focused. As for enabled and checked, you need to manually lift the state up to the point from where every component that needs to know about such states has access to it. I would personally avoid creating composition locals to such cases. It created a level of indirection and implicit dependency that could end up complicating logic and making your components less reusable.
m

Mikołaj Kąkol

10/26/2021, 1:54 PM
thank you for your insight 🙂 I feel that composition local with reasonable defaults wouldn’t cause problems with reusablity. Still in order to work with InteractionSource you need to pass it n levels deep. This is kind of is tedious. In swift ui it's propagated if anyone is interested in comparison.
m

maciejciemiega

10/26/2021, 2:47 PM
Out of curiosity, can you point to some samples to see how it's done in SwiftUI? 🙂
m

Mikołaj Kąkol

10/26/2021, 5:27 PM
My colleague: States press/focus/check are handled inside function call via styles. Style impl has access to configuration which has information about mentioned states. When it comes to disabled, it’s set by disabled modifier, which underhood uses preferenceKey mechanism which allows to each function call to access to certain properties.
this preferenceKey is basically composition local
@matvei do you have any suggestions? Or maybe you know why it's not already built in?
m

matvei

10/27/2021, 5:00 PM
Such information (both interactions like pressed, hovered and state like enabled/checked etc) is the widget's state. We recommend against using composition locals to propagate state down the hierarchy, because it creates implicit dependency between components. Assume you have a checkbox and a text that you want to paint differently depending on this checkbox's state. In this case, text depends on the state of the checkbox or even on the state of the screen/feature/etc. Propagating such information via composition locals, while might be tempting at first, will make logic hard to understand, hard to support (to add new features, remove features) and error-prone. It feels like a boilerplate to "drill-down" state to a few places instead of one, but essentially it's the opposite - you are clearly stating the contracts between components, their states and the state of the screen. We don't have any plans to add anything like Swift has in compose any time soon because of the reasons above.
m

Mikołaj Kąkol

10/27/2021, 5:04 PM
Thank you very much for clarification 😊
16 Views