Hi, I'm learning compose and was wondering if I ca...
# compose
t
Hi, I'm learning compose and was wondering if I can reuse a Modifier. I created a file 'Modifiers.kt' that contain modifiers I want to reuse, f.e.
Copy code
val dialogModifier = Modifier
    .padding(10.dp)
    .background(MaterialTheme.colors.surface)
    .width(400.dp)
But then build is failing with: @Composable invocations can only happen from the context of a @Composable function . What am I doing wrong?
a
MaterialTheme.colors
can only be dereferenced inside a
@Composable
function.
Its value is not a constant like
10.dp
, it’s composition-dependent. So you can’t just use it.
But you can do
Copy code
@Composable
fun dialogModifier() = ...
t
Thank you for your help and explanation. I appreciate that! It's compiling when I refactor it as function as you proposed, but in this specific case padding gets just ignored, while background and width is applied correct.
After further investigation I realized that it's actually working when I change the order and put padding after width. If there's an explanation to that behaviour I'm glad to hear but anyway thanks so far, my issue is solved!
a
The order of the modifiers matters
☝🏽 1
☝️ 3
if you put padding then width then the padding is “outside” the width”, and vice versa.
a
Like if you put .border(Color.Red).border(Color.Blue) you will have a blue border inside a red border.
t
Ah, that makes sense and is actually a nice behavior! 👌 Thanks again guys! 😀
m
FYI: Your other option for using composable content to build modifiers is the
composed
function. There's subtle differences in using this as opposed to just marking a function with @Composable. If you mark your function with @Composable as @Alexander Maryanovsky suggested, any composable references will be evaluated at the time of the function invocation. If you use the
composed
function, it happens a bit later in the recomposition. The official description:
Copy code
Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.
https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).com[…](kotlin.Function1,kotlin.Function1)
1
a
Yes, Modifiers are designed to be reusable.
Modifier.composed
is the way to create a modifier factory that will be invoked at each usage site to preserve this reusability by giving you a place to create and
remember
point of use instance-specific information.
a
Can you guys elaborate on that? I'm not sure I understand what it does.
Ah, I think I understand. It lets the modifier become part of the composition, including having its own state.
a
right. In essence every
@Composable
function (including lambdas) is a factory for instances of that content in a composition. They can be reused in multiple places and keep instance-specific state.
Modifier.composed {}
gives that same capability to modifiers and lets you assemble them into a chain with other modifiers like you would expect