I'm trying to add some conditional logic to the modifier parameter in my custom composable before using it. How can this be done? For example
@Composable
fun MyComposable(index: Int, myModifier: Modifier = Modifier) {
if (index == 0) {
myModifier.background(Color.Red)
} else {
myModifier.background(Color.Blue)
}
Column(modifier = myModifier) {
...
}
Compose simply ignores changes made to myModifier
For now, I'm creating a new variable of type Modifier and using that instead, but I'm wondering if there is a better way using the original passed-in modifier.
CodePudding user response:
Compose simply ignores changes made to myModifier
It doesn't ignore but when you chain Modifiers you create new instance of Modifier if any part of it has changed.
And Modifiers also get recomposed when the variable they read changes, in your instance when Modifier.background()
changes there is a new Modifier created using part of the Modifier that doesn't change, in the example below size and the new Modifier for background.
You need to assign this new Modifier to your Composables
@Composable
private fun ModifierRecompositionSample() {
var counter by remember { mutableStateOf(0) }
Column {
val myModifier = Modifier.fillMaxWidth()
Text(text = "MyModifier: $myModifier", modifier = myModifier)
val newModifier = if (counter == 0) {
myModifier.background(Color.Red)
} else {
myModifier.background(Color.Blue)
}
Text(text = "MyModifier: $myModifier", modifier = myModifier)
Text(
color = Color.White,
text = "newModifier: ${newModifier.hashCode()}, newModifier: $newModifier",
modifier = newModifier
)
Button(onClick = { counter }) {
Text("Counter: $counter")
}
}
}
You can check out this question if you with to investigate composition phases and Modifier recomposition
How I can display data for specific item
CodePudding user response:
Its not being ignored, but it won't work by simply calling
myModifier.background( <color> )
because you aren't setting it to the same Modifier
instance or any Modifier
instance that your Column
will use.
You cannot do this and it won't compile
@Composable
fun MyComposable(index: Int, myModifier : Modifier = Modifier) {
myModifier = if (index == 0) {
Modifier.background(Color.Red)
} else {
Modifier.background(Color.Blue)
}
Column(modifier = myModifier) { ... }
}
because the Modifier
parameter (myModifier) is implicitly val
and its final
, so you'll see a compile error
Val cannot be reassigned
However you can do something like this,
@Composable
fun MyComposable(index: Int) {
val myModifier = if (index == 0) {
Modifier.background(Color.Red)
} else {
Modifier.background(Color.Blue)
}
Column(modifier = myModifier) { ... }
}
or something like this,
@Composable
fun MyComposable(
index : Int,
myModifier: Modifier = Modifier
) {
Column(
modifier = myModifier
.background(
if (index == 0) Color.Red else Color.Blue
)
) { ... }
}
or when passing it to the MyComposable
. I'm assuming that index
is just used for a conditional background color though so I removed it as a parameter below
// ... Somewhere in your composable outside ...
val index = 5
MyComposable(
// removed index arg
myModifier = Modifier
.background(
if (index == 0) Color.Red else Color.Blue
)
)
}
...
...
...
@Composable
fun MyComposable(
// removed index param
myModifier: Modifier = Modifier
) {
Column(modifier = myModifier)
) { ... }
}
I personally prefer the third approach, where Modifier
properties of a root/parent composable are controlled outside, in your case the Column
(root/parent) background of your MyComposable
contents.