Kyant
12/26/2025, 7:12 AMLayoutModifierNode + DrawModifierNode + placeable.placeWithLayer ?
It only works with node.invalidateDrawForSubtree(), and node.invalidateDraw() doesn't work.Kyant
12/26/2025, 7:14 AMimport androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.node.invalidateDraw
import androidx.compose.ui.node.updateLayerBlock
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.IntOffset
fun Modifier.fillClip(
color: Color,
shape: Shape,
blendMode: BlendMode = BlendMode.SrcOver
) = this then FillClipElement(color, shape, blendMode)
private data class FillClipElement(
val color: Color,
val shape: Shape,
val blendMode: BlendMode
) : ModifierNodeElement<FillClipNode>() {
override fun create(): FillClipNode = FillClipNode(color, shape, blendMode)
override fun update(node: FillClipNode) {
node.color = color
node.shape = shape
node.blendMode = blendMode
node.invalidateLayerBlock()
node.invalidateDraw()
}
override fun InspectorInfo.inspectableProperties() {
name = "fillClip"
properties["color"] = color
properties["shape"] = shape
properties["blendMode"] = blendMode
}
}
private class FillClipNode(
var color: Color,
var shape: Shape,
var blendMode: BlendMode
) : LayoutModifierNode, DrawModifierNode, Modifier.Node() {
override val shouldAutoInvalidate: Boolean = false
private val layerBlock: GraphicsLayerScope.() -> Unit = {
clip = true
shape = this@FillClipNode.shape
}
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints,
): MeasureResult {
val placeable = measurable.measure(constraints)
return layout(placeable.width, placeable.height) {
placeable.placeWithLayer(IntOffset.Zero, layerBlock = layerBlock)
}
}
override fun ContentDrawScope.draw() {
drawRect(color, blendMode = blendMode)
drawContent()
}
fun invalidateLayerBlock() {
updateLayerBlock(layerBlock)
}
}Louis Pullen-Freilich [G]
12/27/2025, 1:27 PMLouis Pullen-Freilich [G]
12/27/2025, 1:29 PMupdateLayerBlock should work, you just need to use a mutable variable and assign a new lambda I think?Louis Pullen-Freilich [G]
12/27/2025, 1:30 PM