New Backdrop API

This commit is contained in:
Kyant0 committed 2025-09-23 12:04:13 +08:00
1 parent 5abcb17389
commit 4841314568
21 files changed
+329 -244

No files matched your search

@@ -1,69 +1,17 @@
package com.kyant.backdrop
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
private val DefaultDrawLayer: ContentDrawScope.() -> Unit = { drawContent() }
interface Backdrop {
@Composable
fun rememberBackdrop(
graphicsLayer: GraphicsLayer = rememberGraphicsLayer(),
drawLayer: ContentDrawScope.() -> Unit = DefaultDrawLayer
): Backdrop {
return remember(graphicsLayer, drawLayer) {
Backdrop(
graphicsLayer = graphicsLayer,
drawLayer = drawLayer
)
}
}
val isCoordinatesDependent: Boolean
@Stable
class Backdrop internal constructor(
val graphicsLayer: GraphicsLayer,
internal val drawLayer: ContentDrawScope.() -> Unit
) : BackdropDrawer {
internal var backdropCoordinates: LayoutCoordinates? by mutableStateOf(null)
private var inverseLayerScope: InverseLayerScope? = null
override fun DrawScope.drawBackdrop(
fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
val backdropCoordinates = backdropCoordinates ?: return
val offset = backdropCoordinates.localPositionOf(coordinates)
val layerBlock = layerBlock
if (layerBlock != null) {
withTransform({
val inverseLayerScope =
inverseLayerScope?.apply { reset() }
?: InverseLayerScope().also { inverseLayerScope = it }
with(inverseLayerScope) { inverseTransform(density, layerBlock) }
translate(-offset.x, -offset.y)
}) {
drawLayer(graphicsLayer)
}
} else {
translate(-offset.x, -offset.y) {
drawLayer(graphicsLayer)
}
}
}
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)? = null
)
}
@@ -1,40 +0,0 @@
package com.kyant.backdrop
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
private val DefaultOnDrawBackdrop: DrawScope.(DrawScope.() -> Unit) -> Unit = { it() }
@Composable
fun rememberBackdropDrawer(
backdrop: BackdropDrawer,
onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit = DefaultOnDrawBackdrop
): BackdropDrawer {
return remember(backdrop, onDrawBackdrop) {
object : BackdropDrawer {
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
onDrawBackdrop {
with(backdrop) { drawBackdrop(density, coordinates, layerBlock) }
}
}
}
}
}
interface BackdropDrawer {
fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
layerBlock: (GraphicsLayerScope.() -> Unit)? = null
)
}
@@ -1,55 +0,0 @@
package com.kyant.backdrop
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
@Composable
fun rememberCombinedBackdropDrawer(backdrop1: BackdropDrawer, backdrop2: BackdropDrawer): BackdropDrawer {
return remember(backdrop1, backdrop2) {
CombinedBackdropDrawer(backdrop1, backdrop2)
}
}
@Composable
fun rememberCombinedBackdropDrawer(vararg backdrops: BackdropDrawer): BackdropDrawer {
return remember(*backdrops) {
CombinedBackdropsDrawer(*backdrops)
}
}
@Stable
private class CombinedBackdropDrawer(
val backdrop1: BackdropDrawer,
val backdrop2: BackdropDrawer
) : BackdropDrawer {
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
with(backdrop1) { drawBackdrop(density, coordinates, layerBlock) }
with(backdrop2) { drawBackdrop(density, coordinates, layerBlock) }
}
}
@Stable
private class CombinedBackdropsDrawer(
vararg val backdrops: BackdropDrawer
) : BackdropDrawer {
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
backdrops.forEach {
with(it) { drawBackdrop(density, coordinates, layerBlock) }
}
}
}
@@ -70,7 +70,7 @@ fun Modifier.contentBackdrop(
.then(
ContentBackdropElement(
shapeProvider = shapeProvider,
layerBlock = layer,
layer = layer,
onDrawBehind = onDrawBehind,
onDrawSurface = onDrawSurface,
effects = effects
@@ -80,7 +80,7 @@ fun Modifier.contentBackdrop(
private class ContentBackdropElement(
val shapeProvider: ShapeProvider,
var layerBlock: (GraphicsLayerScope.() -> Unit)?,
val layer: (GraphicsLayerScope.() -> Unit)?,
val onDrawBehind: (DrawScope.() -> Unit)?,
val onDrawSurface: (DrawScope.() -> Unit)?,
val effects: BackdropEffectScope.() -> Unit
@@ -89,7 +89,7 @@ private class ContentBackdropElement(
override fun create(): ContentBackdropNode {
return ContentBackdropNode(
shapeProvider = shapeProvider,
layerBlock = layerBlock,
layer = layer,
onDrawBehind = onDrawBehind,
onDrawSurface = onDrawSurface,
effects = effects
@@ -98,7 +98,7 @@ private class ContentBackdropElement(
override fun update(node: ContentBackdropNode) {
node.shapeProvider = shapeProvider
node.layerBlock = layerBlock
node.layer = layer
node.onDrawBehind = onDrawBehind
node.onDrawSurface = onDrawSurface
node.effects = effects
@@ -108,7 +108,7 @@ private class ContentBackdropElement(
override fun InspectorInfo.inspectableProperties() {
name = "contentBackdrop"
properties["shapeProvider"] = shapeProvider
properties["layerBlock"] = layerBlock
properties["layer"] = layer
properties["onDrawBehind"] = onDrawBehind
properties["onDrawSurface"] = onDrawSurface
properties["effects"] = effects
@@ -119,7 +119,7 @@ private class ContentBackdropElement(
if (other !is ContentBackdropElement) return false
if (shapeProvider != other.shapeProvider) return false
if (layerBlock != other.layerBlock) return false
if (layer != other.layer) return false
if (onDrawBehind != other.onDrawBehind) return false
if (onDrawSurface != other.onDrawSurface) return false
if (effects != other.effects) return false
@@ -129,7 +129,7 @@ private class ContentBackdropElement(
override fun hashCode(): Int {
var result = shapeProvider.hashCode()
result = 31 * result + (layerBlock?.hashCode() ?: 0)
result = 31 * result + (layer?.hashCode() ?: 0)
result = 31 * result + (onDrawBehind?.hashCode() ?: 0)
result = 31 * result + (onDrawSurface?.hashCode() ?: 0)
result = 31 * result + effects.hashCode()
@@ -139,7 +139,7 @@ private class ContentBackdropElement(
private class ContentBackdropNode(
var shapeProvider: ShapeProvider,
var layerBlock: (GraphicsLayerScope.() -> Unit)?,
var layer: (GraphicsLayerScope.() -> Unit)?,
var onDrawBehind: (DrawScope.() -> Unit)?,
var onDrawSurface: (DrawScope.() -> Unit)?,
var effects: BackdropEffectScope.() -> Unit
@@ -159,7 +159,7 @@ private class ContentBackdropNode(
null
}
private val layoutLayerBlock: GraphicsLayerScope.() -> Unit = {
private val layerBlock: GraphicsLayerScope.() -> Unit = {
clip = true
shape = shapeProvider.shape
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
@@ -173,7 +173,7 @@ private class ContentBackdropNode(
): MeasureResult {
val placeable = measurable.measure(constraints)
return layout(placeable.width, placeable.height) {
placeable.placeWithLayer(IntOffset.Zero, layerBlock = layoutLayerBlock)
placeable.placeWithLayer(IntOffset.Zero, layerBlock = layerBlock)
}
}
@@ -188,11 +188,9 @@ private class ContentBackdropNode(
val layer = graphicsLayer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && layer != null) {
layer.record {
this@draw.drawContent()
}
layer.record { this@draw.drawContent() }
val layerBlock = layerBlock
val layerBlock = this@ContentBackdropNode.layer
if (layerBlock != null) {
withTransform({
val inverseLayerScope =
@@ -0,0 +1,38 @@
package com.kyant.backdrop
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import com.kyant.backdrop.backdrops.LayerBackdrop
import com.kyant.backdrop.backdrops.layerBackdrop
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
private val DefaultDrawLayer: ContentDrawScope.() -> Unit = { drawContent() }
@Deprecated(
message = "Use rememberLayerBackdrop instead",
replaceWith = ReplaceWith(
"rememberLayerBackdrop(graphicsLayer = graphicsLayer)",
"com.kyant.backdrop.backdrops.rememberLayerBackdrop",
"androidx.compose.ui.graphics.rememberGraphicsLayer"
)
)
@Composable
fun rememberBackdrop(
graphicsLayer: GraphicsLayer = rememberGraphicsLayer(),
drawLayer: ContentDrawScope.() -> Unit = DefaultDrawLayer
): LayerBackdrop {
return rememberLayerBackdrop(graphicsLayer, drawLayer)
}
@Deprecated(
message = "Use layerBackdrop instead",
replaceWith = ReplaceWith(
"this.layerBackdrop(backdrop)",
"com.kyant.backdrop.backdrops.layerBackdrop"
)
)
fun Modifier.backdrop(backdrop: LayerBackdrop): Modifier =
this.layerBackdrop(backdrop)
@@ -3,6 +3,7 @@ package com.kyant.backdrop
import android.os.Build
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.neverEqualPolicy
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.GraphicsLayerScope
@@ -40,7 +41,7 @@ internal val DefaultShadow = { Shadow.Default }
private val DefaultOnDrawBackdrop: DrawScope.(DrawScope.() -> Unit) -> Unit = { it() }
fun Modifier.drawBackdrop(
backdrop: BackdropDrawer,
backdrop: Backdrop,
shape: () -> Shape,
highlight: (() -> Highlight?)? = DefaultHighlight,
shadow: (() -> Shadow?)? = DefaultShadow,
@@ -84,7 +85,7 @@ fun Modifier.drawBackdrop(
DrawBackdropElement(
backdrop = backdrop,
shapeProvider = shapeProvider,
layerBlock = layer,
layer = layer,
onDrawBehind = onDrawBehind,
onDrawBackdrop = onDrawBackdrop,
onDrawSurface = onDrawSurface,
@@ -95,9 +96,9 @@ fun Modifier.drawBackdrop(
}
private class DrawBackdropElement(
val backdrop: BackdropDrawer,
val backdrop: Backdrop,
val shapeProvider: ShapeProvider,
val layerBlock: (GraphicsLayerScope.() -> Unit)?,
val layer: (GraphicsLayerScope.() -> Unit)?,
val onDrawBehind: (DrawScope.() -> Unit)?,
val onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit,
val onDrawSurface: (DrawScope.() -> Unit)?,
@@ -109,7 +110,7 @@ private class DrawBackdropElement(
return DrawBackdropNode(
backdrop = backdrop,
shapeProvider = shapeProvider,
layerBlock = layerBlock,
layer = layer,
onDrawBehind = onDrawBehind,
onDrawBackdrop = onDrawBackdrop,
onDrawSurface = onDrawSurface,
@@ -121,7 +122,7 @@ private class DrawBackdropElement(
override fun update(node: DrawBackdropNode) {
node.backdrop = backdrop
node.shapeProvider = shapeProvider
node.layerBlock = layerBlock
node.layer = layer
node.onDrawBehind = onDrawBehind
node.onDrawBackdrop = onDrawBackdrop
node.onDrawSurface = onDrawSurface
@@ -134,7 +135,7 @@ private class DrawBackdropElement(
name = "drawBackdrop"
properties["backdrop"] = backdrop
properties["shapeProvider"] = shapeProvider
properties["layerBlock"] = layerBlock
properties["layer"] = layer
properties["onDrawBehind"] = onDrawBehind
properties["onDrawBackdrop"] = onDrawBackdrop
properties["onDrawSurface"] = onDrawSurface
@@ -148,7 +149,7 @@ private class DrawBackdropElement(
if (backdrop != other.backdrop) return false
if (shapeProvider != other.shapeProvider) return false
if (layerBlock != other.layerBlock) return false
if (layer != other.layer) return false
if (onDrawBehind != other.onDrawBehind) return false
if (onDrawBackdrop != other.onDrawBackdrop) return false
if (onDrawSurface != other.onDrawSurface) return false
@@ -161,7 +162,7 @@ private class DrawBackdropElement(
override fun hashCode(): Int {
var result = backdrop.hashCode()
result = 31 * result + shapeProvider.hashCode()
result = 31 * result + (layerBlock?.hashCode() ?: 0)
result = 31 * result + (layer?.hashCode() ?: 0)
result = 31 * result + (onDrawBehind?.hashCode() ?: 0)
result = 31 * result + onDrawBackdrop.hashCode()
result = 31 * result + (onDrawSurface?.hashCode() ?: 0)
@@ -172,9 +173,9 @@ private class DrawBackdropElement(
}
private class DrawBackdropNode(
var backdrop: BackdropDrawer,
var backdrop: Backdrop,
var shapeProvider: ShapeProvider,
var layerBlock: (GraphicsLayerScope.() -> Unit)?,
var layer: (GraphicsLayerScope.() -> Unit)?,
var onDrawBehind: (DrawScope.() -> Unit)?,
var onDrawBackdrop: DrawScope.(drawBackdrop: DrawScope.() -> Unit) -> Unit,
var onDrawSurface: (DrawScope.() -> Unit)?,
@@ -185,7 +186,18 @@ private class DrawBackdropNode(
override val shouldAutoInvalidate: Boolean = false
private var graphicsLayer: GraphicsLayer? = null
private var recordBlock: (DrawScope.() -> Unit)? by mutableStateOf(null)
private var layoutCoordinates: LayoutCoordinates? by mutableStateOf(null, neverEqualPolicy())
private val recordBlock: (DrawScope.() -> Unit) = {
onDrawBackdrop {
with(backdrop) {
drawBackdrop(
density = mutableDensity,
coordinates = layoutCoordinates,
layerBlock = layer
)
}
}
}
private val effectScope =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -197,7 +209,7 @@ private class DrawBackdropNode(
null
}
private val layoutLayerBlock: GraphicsLayerScope.() -> Unit = {
private val layerBlock: GraphicsLayerScope.() -> Unit = {
clip = true
shape = shapeProvider.shape
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
@@ -216,7 +228,7 @@ private class DrawBackdropNode(
): MeasureResult {
val placeable = measurable.measure(constraints)
return layout(placeable.width, placeable.height) {
placeable.placeWithLayer(IntOffset.Zero, layerBlock = layoutLayerBlock)
placeable.placeWithLayer(IntOffset.Zero, layerBlock = layerBlock)
}
}
@@ -231,7 +243,7 @@ private class DrawBackdropNode(
val layer = graphicsLayer
val recordBlock = recordBlock
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && layer != null && recordBlock != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && layer != null) {
mutableDensity.density = density
mutableDensity.fontScale = fontScale
layer.record(
@@ -242,7 +254,7 @@ private class DrawBackdropNode(
)
drawLayer(layer)
} else {
recordBlock?.invoke(this)
recordBlock()
}
onDrawSurface?.invoke(this)
@@ -254,15 +266,11 @@ private class DrawBackdropNode(
override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
if (coordinates.isAttached) {
recordBlock = {
onDrawBackdrop {
with(backdrop) {
drawBackdrop(
density = mutableDensity,
coordinates = coordinates,
layerBlock = layerBlock
)
}
if (backdrop.isCoordinatesDependent) {
layoutCoordinates = coordinates
} else {
if (layoutCoordinates != null) {
layoutCoordinates = null
}
}
}
@@ -303,7 +311,7 @@ private class DrawBackdropNode(
graphicsContext.releaseGraphicsLayer(layer)
graphicsLayer = null
}
recordBlock = null
layoutCoordinates = null
effectScope?.reset()
}
}
@@ -0,0 +1,24 @@
package com.kyant.backdrop.backdrops
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
import com.kyant.backdrop.Backdrop
@Immutable
class CanvasBackdrop(
val onDraw: DrawScope.() -> Unit
) : Backdrop {
override val isCoordinatesDependent: Boolean = false
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
onDraw()
}
}
@@ -0,0 +1,98 @@
package com.kyant.backdrop.backdrops
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
import com.kyant.backdrop.Backdrop
@Composable
fun rememberCombinedBackdrop(
backdrop1: Backdrop,
backdrop2: Backdrop
): Backdrop {
return remember(backdrop1, backdrop2) {
Combined2Backdrops(backdrop1, backdrop2)
}
}
@Composable
fun rememberCombinedBackdrop(
backdrop1: Backdrop,
backdrop2: Backdrop,
backdrop3: Backdrop
): Backdrop {
return remember(backdrop1, backdrop2, backdrop3) {
Combined3Backdrops(backdrop1, backdrop2, backdrop3)
}
}
@Composable
fun rememberCombinedBackdrop(vararg backdrops: Backdrop): Backdrop {
return remember(*backdrops) {
CombinedBackdrops(*backdrops)
}
}
@Immutable
private class Combined2Backdrops(
val backdrop1: Backdrop,
val backdrop2: Backdrop
) : Backdrop {
override val isCoordinatesDependent: Boolean =
backdrop1.isCoordinatesDependent || backdrop2.isCoordinatesDependent
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
with(backdrop1) { drawBackdrop(density, coordinates, layerBlock) }
with(backdrop2) { drawBackdrop(density, coordinates, layerBlock) }
}
}
@Immutable
private class Combined3Backdrops(
val backdrop1: Backdrop,
val backdrop2: Backdrop,
val backdrop3: Backdrop
) : Backdrop {
override val isCoordinatesDependent: Boolean =
backdrop1.isCoordinatesDependent ||
backdrop2.isCoordinatesDependent ||
backdrop3.isCoordinatesDependent
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
with(backdrop1) { drawBackdrop(density, coordinates, layerBlock) }
with(backdrop2) { drawBackdrop(density, coordinates, layerBlock) }
with(backdrop3) { drawBackdrop(density, coordinates, layerBlock) }
}
}
@Immutable
private class CombinedBackdrops(
vararg val backdrops: Backdrop
) : Backdrop {
override val isCoordinatesDependent: Boolean = backdrops.any { it.isCoordinatesDependent }
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
backdrops.forEach {
with(it) { drawBackdrop(density, coordinates, layerBlock) }
}
}
}
@@ -1,17 +1,22 @@
package com.kyant.backdrop
package com.kyant.backdrop.backdrops
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
import com.kyant.backdrop.Backdrop
fun emptyBackdrop(): Backdrop = EmptyBackdrop
@Immutable
object EmptyBackdropDrawer : BackdropDrawer {
private object EmptyBackdrop : Backdrop {
override val isCoordinatesDependent: Boolean = false
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
}
@@ -0,0 +1,70 @@
package com.kyant.backdrop.backdrops
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.unit.Density
import com.kyant.backdrop.Backdrop
import com.kyant.backdrop.InverseLayerScope
private val DefaultDrawLayer: ContentDrawScope.() -> Unit = { drawContent() }
@Composable
fun rememberLayerBackdrop(
graphicsLayer: GraphicsLayer = rememberGraphicsLayer(),
drawLayer: ContentDrawScope.() -> Unit = DefaultDrawLayer
): LayerBackdrop {
return remember(graphicsLayer, drawLayer) {
LayerBackdrop(graphicsLayer, drawLayer)
}
}
@Stable
class LayerBackdrop internal constructor(
val graphicsLayer: GraphicsLayer,
internal val drawLayer: ContentDrawScope.() -> Unit
) : Backdrop {
override val isCoordinatesDependent: Boolean = true
internal var backdropCoordinates: LayoutCoordinates? by mutableStateOf(null)
private var inverseLayerScope: InverseLayerScope? = null
override fun DrawScope.drawBackdrop(
density: Density,
coordinates: LayoutCoordinates?,
layerBlock: (GraphicsLayerScope.() -> Unit)?
) {
val backdropCoordinates = backdropCoordinates ?: return
val offset = backdropCoordinates.localPositionOf(coordinates ?: return)
val layerBlock = layerBlock
if (layerBlock != null) {
withTransform({
val inverseLayerScope =
inverseLayerScope?.apply { reset() }
?: InverseLayerScope().also { inverseLayerScope = it }
with(inverseLayerScope) { inverseTransform(density, layerBlock) }
translate(-offset.x, -offset.y)
}) {
drawLayer(graphicsLayer)
}
} else {
translate(-offset.x, -offset.y) {
drawLayer(graphicsLayer)
}
}
}
}
@@ -1,4 +1,4 @@
package com.kyant.backdrop
package com.kyant.backdrop.backdrops
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
@@ -10,28 +10,30 @@ import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.node.invalidateDraw
import androidx.compose.ui.platform.InspectorInfo
fun Modifier.backdrop(backdrop: Backdrop): Modifier =
this then BackdropElement(backdrop)
fun Modifier.layerBackdrop(backdrop: LayerBackdrop): Modifier =
this then LayerBackdropElement(backdrop)
private class BackdropElement(val backdrop: Backdrop) : ModifierNodeElement<BackdropNode>() {
private class LayerBackdropElement(
val backdrop: LayerBackdrop
) : ModifierNodeElement<LayerBackdropNode>() {
override fun create(): BackdropNode {
return BackdropNode(backdrop = backdrop)
override fun create(): LayerBackdropNode {
return LayerBackdropNode(backdrop)
}
override fun update(node: BackdropNode) {
override fun update(node: LayerBackdropNode) {
node.backdrop = backdrop
node.invalidateDraw()
}
override fun InspectorInfo.inspectableProperties() {
name = "backdrop"
name = "layerBackdrop"
properties["backdrop"] = backdrop
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is BackdropElement) return false
if (other !is LayerBackdropElement) return false
if (backdrop != other.backdrop) return false
@@ -43,8 +45,9 @@ private class BackdropElement(val backdrop: Backdrop) : ModifierNodeElement<Back
}
}
private class BackdropNode(var backdrop: Backdrop) :
DrawModifierNode, GlobalPositionAwareModifierNode, Modifier.Node() {
private class LayerBackdropNode(
var backdrop: LayerBackdrop
) : DrawModifierNode, GlobalPositionAwareModifierNode, Modifier.Node() {
override val shouldAutoInvalidate: Boolean = false