lilypuchi
07/25/2023, 1:36 AMModifier
as follows
fun Modifier.selectedBackground(isSelected: Boolean): Modifier = if (isSelected) {
composed {
val alpha = if (isSelected) 0.16f else 0.22f
Modifier.background(MaterialTheme.colorScheme.secondary.copy(alpha = alpha))
}
}
I want to migrate it to Modifier.Node
like,
private class SelectedBackgroundNode(
var isSelected: Boolean
): CompositionLocalConsumerModifierNode, DrawModifierNode, Modifier.Node() {
override fun ContentDrawScope.draw() {
val backgroundColor = currentValue(MaterialTheme.colorScheme).background
drawRect(color = backgroundColor, alpha = if (isSelected) 0.16f else 0.22f)
drawContent()
}
}
However, since MaterialTheme.colorScheme
is basically LocalColorScheme.current
and LocalColorScheme
is internal, I’m unable to access it. The only way is passing backgroundColor
as a parameter to SelectedBackgroundNode
.
An alternative could be declaring a new CompositionLocal LocalAppColorScheme provides MaterialTheme.colorScheme
and use it. Is there any better way of accessing MaterialTheme.colorScheme
myanmarking
07/25/2023, 9:17 AMmyanmarking
07/25/2023, 9:23 AM@Composable
fun Modifier.selectedBackground(
color: Color = MaterialTheme.colorScheme.secondary.copy(alpha = 0.16f),
colorDisabled: Color = MaterialTheme.colorScheme.secondary.copy(alpha = 0.22f),
enabled: Boolean
): Modifier = this.then(
Modifier.drawBehind {
drawRect(
if(enabled) color else colorDisabled
)
}
)
myanmarking
07/25/2023, 9:25 AMmyanmarking
07/25/2023, 9:26 AMLoney Chou
07/26/2023, 2:09 AM@Composable fun <http://Modifier.xxx|Modifier.xxx>(): Modifier
pattern, use Modifier.composed
at least. The former has potential problem that you can't realize quickly, and it doesn't save much typing.Loney Chou
07/26/2023, 2:16 AMModifier.composed
. There are scenarios where you'd have to use composed
.myanmarking
07/30/2023, 8:11 PMLoney Chou
07/31/2023, 2:13 AM@Composable
fun Modifier.bad(): Modifier {
return background(LocalContentColor.current)
}
fun Modifier.good(): Modifier {
return composed {
background(LocalContentColor.current)
}
}
@Composable
fun TestBad() {
val reusedModifier = Modifier
.bad()
.size(20.dp)
Box(modifier = reusedModifier)
Button(
onClick = {}
) {
Box(modifier = reusedModifier)
}
}
@Composable
fun TestGood() {
val reusedModifier = Modifier
.good()
.size(20.dp)
Box(modifier = reusedModifier)
Button(
onClick = {}
) {
Box(modifier = reusedModifier)
}
}
The bad one behaves differently because Modifier.bad
reads state in place, so inside Button it's not the actual LocalContentColor, instead it's that from outside Button.
The best practice is to use Modifier.Node. However since LocalColorScheme is internal, we need to use some technique in order to access:
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
import androidx.compose.material3.LocalColorScheme
LocalColorScheme // You made it!
Well, if you'd prefer the simpler one, just use it and have that in mind. I'd like the modifier to be more robust and context-free so I can reuse.myanmarking
08/02/2023, 6:53 PMLoney Chou
08/03/2023, 4:28 PMreturn background
is return this then BackgroundElement
under the hood. The second one will be return this then Modifier.background
effectively which is then also return this then BackgroundElement
.myanmarking
08/03/2023, 4:31 PMLoney Chou
08/03/2023, 4:32 PMmyanmarking
08/03/2023, 4:34 PMmyanmarking
08/03/2023, 4:35 PMmyanmarking
08/03/2023, 4:37 PMLoney Chou
08/03/2023, 4:38 PMWell, if you'd prefer the simpler one, just use it and have that in mind. I'd like the modifier to be more robust and context-free so I can reuse.
myanmarking
08/03/2023, 4:38 PM