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.colorSchememyanmarking
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