diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt index 81e4bc5..876f1b8 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt @@ -1,34 +1,26 @@ package com.kyant.backdrop.highlight -import android.graphics.Bitmap -import android.graphics.BitmapShader -import android.graphics.BlendMode import android.graphics.BlurMaskFilter -import android.graphics.Canvas -import android.graphics.Color import android.graphics.Paint import android.graphics.Path -import android.graphics.PorterDuff -import android.graphics.RectF import android.graphics.RuntimeShader -import android.graphics.Shader import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.asAndroidPath -import androidx.compose.ui.graphics.asComposePaint import androidx.compose.ui.graphics.drawscope.ContentDrawScope import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.isUnspecified +import androidx.compose.ui.graphics.layer.CompositingStrategy +import androidx.compose.ui.graphics.layer.GraphicsLayer +import androidx.compose.ui.graphics.layer.drawLayer import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.node.DrawModifierNode import androidx.compose.ui.node.ModifierNodeElement -import androidx.compose.ui.node.ObserverModifierNode import androidx.compose.ui.node.invalidateDraw -import androidx.compose.ui.node.observeReads +import androidx.compose.ui.node.requireGraphicsContext import androidx.compose.ui.platform.InspectorInfo import androidx.compose.ui.util.fastCoerceAtMost import com.kyant.backdrop.RuntimeShaderCacheScope @@ -47,7 +39,7 @@ internal class HighlightElement( override fun update(node: HighlightNode) { node.shapeProvider = shapeProvider node.highlight = highlight - node.invalidateDrawCache() + node.invalidateDraw() } override fun InspectorInfo.inspectableProperties() { @@ -76,19 +68,17 @@ internal class HighlightElement( internal class HighlightNode( var shapeProvider: ShapeProvider, var highlight: () -> Highlight? -) : DrawModifierNode, ObserverModifierNode, Modifier.Node() { +) : DrawModifierNode, Modifier.Node() { override val shouldAutoInvalidate: Boolean = false - private var bitmap: Bitmap? = null - private var canvas: Canvas? = null - private var bitmapShader: BitmapShader? = null + private var highlightLayer: GraphicsLayer? = null + private var maskLayer: GraphicsLayer? = null + private val paint = Paint().apply { style = Paint.Style.STROKE } - private val shaderPaint = Paint() - private var prevSize = Size.Unspecified private var clipPath: Path? = null private val runtimeShaderCacheScope = object : RuntimeShaderCacheScope { @@ -101,66 +91,81 @@ internal class HighlightNode( } } - private var isCacheValid = false - private var _highlight: Highlight? = null - private val cacheDrawBlock: DrawScope.() -> Unit = cacheDrawBlock@{ - val highlight = highlight().also { _highlight = it } - val size = size - if (highlight == null || - highlight.width.value <= 0f || highlight.color.isUnspecified || highlight.alpha == 0f || - size.width < 0.5f || size.height < 0.5f - ) { - _highlight = null - return@cacheDrawBlock + private var prevStyle: HighlightStyle? = null + + override fun ContentDrawScope.draw() { + val highlight = highlight() + if (highlight == null || highlight.width.value <= 0f || highlight.color.isUnspecified) { + return drawContent() } - val color = - if (highlight.alpha == 1f) { - highlight.color - } else { - highlight.color.copy(alpha = highlight.color.alpha * highlight.alpha) + drawContent() + + val highlightLayer = highlightLayer + val maskLayer = maskLayer + if (highlightLayer != null && maskLayer != null) { + val size = size + val outline = shapeProvider.shape.createOutline(size, layoutDirection, this) + + configurePaint(highlight) + + val style = highlight.style() + if (prevStyle != style) { + highlightLayer.renderEffect = + with(highlight.style()) { runtimeShaderCacheScope.createRenderEffect(size) } + prevStyle = style } - paint.color = color.toArgb() - val strokeWidth = ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f)) - paint.strokeWidth = strokeWidth * 2f + highlightLayer.record { drawHighlight(outline) } + + maskLayer.alpha = highlight.alpha + maskLayer.blendMode = highlight.blendMode + maskLayer.record { drawLayer(highlightLayer) } + drawLayer(maskLayer) + } + } + + override fun onAttach() { + val graphicsContext = requireGraphicsContext() + highlightLayer = graphicsContext.createGraphicsLayer() + maskLayer = + graphicsContext.createGraphicsLayer().apply { + compositingStrategy = CompositingStrategy.Offscreen + } + } + + override fun onDetach() { + val graphicsContext = requireGraphicsContext() + highlightLayer?.let { layer -> + graphicsContext.releaseGraphicsLayer(layer) + highlightLayer = null + } + maskLayer?.let { layer -> + graphicsContext.releaseGraphicsLayer(layer) + maskLayer = null + } + clipPath = null + prevStyle = null + } + + private fun DrawScope.configurePaint(highlight: Highlight) { + paint.color = highlight.color.toArgb() + paint.strokeWidth = + ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f)) * 2f val blurRadius = highlight.blurRadius.toPx() if (blurRadius > 0f) { paint.maskFilter = BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL) } - shaderPaint.asComposePaint().blendMode = highlight.blendMode + } - if (prevSize != size) { - bitmap = null - canvas = null - prevSize = size - } - - @Suppress("UseKtx") - val bitmap = - bitmap ?: Bitmap.createBitmap( - ceil(size.width).toInt(), - ceil(size.height).toInt(), - Bitmap.Config.ARGB_8888 - ).also { - bitmap = it - bitmapShader = BitmapShader(it, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) - } - val canvas = - canvas?.apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - drawColor(Color.TRANSPARENT, BlendMode.CLEAR) - } else { - drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) - } - } ?: Canvas(bitmap).also { canvas = it } + private fun DrawScope.drawHighlight(outline: Outline) { + val canvas = drawContext.canvas.nativeCanvas canvas.save() - when (val outline = shapeProvider.shape.createOutline(size, layoutDirection, this)) { + when (outline) { is Outline.Rectangle -> { - val rect = RectF(0f, 0f, size.width, size.height) - canvas.clipRect(rect) - canvas.drawRect(rect, paint) + canvas.clipRect(0f, 0f, size.width, size.height) + canvas.drawRect(0f, 0f, size.width, size.height, paint) } is Outline.Rounded -> { @@ -170,12 +175,12 @@ internal class HighlightNode( canvas.clipPath(path) canvas.drawPath(path, paint) } else { - val rect = with(outline.roundRect) { RectF(left, top, right, bottom) } + val rr = outline.roundRect val radius = outline.roundRect.topLeftCornerRadius.x val clipPath = clipPath?.apply { rewind() } ?: Path().also { clipPath = it } - clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW) + clipPath.addRoundRect(rr.left, rr.top, rr.right, rr.bottom, radius, radius, Path.Direction.CW) canvas.clipPath(clipPath) - canvas.drawRoundRect(rect, radius, radius, paint) + canvas.drawRoundRect(rr.left, rr.top, rr.right, rr.bottom, radius, radius, paint) } } @@ -188,38 +193,4 @@ internal class HighlightNode( canvas.restore() } - - override fun ContentDrawScope.draw() { - if (!isCacheValid) { - observeReads { cacheDrawBlock() } - isCacheValid = true - } - - drawContent() - - val highlight = _highlight - val bitmap = bitmap - val bitmapShader = bitmapShader - if (highlight != null && bitmap != null && bitmapShader != null) { - val maskShader = - with(highlight.style()) { runtimeShaderCacheScope.createShader(size, bitmapShader) } - shaderPaint.shader = maskShader - - val canvas = drawContext.canvas.nativeCanvas - if (maskShader != null) { - canvas.drawRect(0f, 0f, size.width, size.height, shaderPaint) - } else { - canvas.drawBitmap(bitmap, 0f, 0f, shaderPaint) - } - } - } - - override fun onObservedReadsChanged() { - invalidateDrawCache() - } - - fun invalidateDrawCache() { - isCacheValid = false - invalidateDraw() - } } diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt index 54cedce..944d5e1 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt @@ -1,12 +1,13 @@ package com.kyant.backdrop.highlight -import android.graphics.BitmapShader -import android.graphics.Shader import android.os.Build import androidx.annotation.FloatRange +import androidx.annotation.RequiresApi import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.RenderEffect +import androidx.compose.ui.graphics.asComposeRenderEffect import androidx.compose.ui.util.lerp import com.kyant.backdrop.AmbientHighlightShaderString import com.kyant.backdrop.DynamicHighlightShaderString @@ -16,18 +17,14 @@ import kotlin.math.PI @Immutable sealed interface HighlightStyle { - fun RuntimeShaderCacheScope.createShader( - size: Size, - bitmapShader: BitmapShader - ): Shader? + @RequiresApi(Build.VERSION_CODES.S) + fun RuntimeShaderCacheScope.createRenderEffect(size: Size): RenderEffect? @Immutable data object Solid : HighlightStyle { - override fun RuntimeShaderCacheScope.createShader( - size: Size, - bitmapShader: BitmapShader - ): Shader? = null + @RequiresApi(Build.VERSION_CODES.S) + override fun RuntimeShaderCacheScope.createRenderEffect(size: Size): RenderEffect? = null } @Immutable @@ -37,10 +34,8 @@ sealed interface HighlightStyle { val isAmbient: Boolean = false ) : HighlightStyle { - override fun RuntimeShaderCacheScope.createShader( - size: Size, - bitmapShader: BitmapShader - ): Shader? { + @RequiresApi(Build.VERSION_CODES.S) + override fun RuntimeShaderCacheScope.createRenderEffect(size: Size): RenderEffect? { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { val shader = if (isAmbient) { @@ -49,11 +44,12 @@ sealed interface HighlightStyle { obtainRuntimeShader("Dynamic", DynamicHighlightShaderString) } shader.apply { - setInputBuffer("image", bitmapShader) setFloatUniform("size", size.width, size.height) setFloatUniform("angle", angle * (PI / 180f).toFloat()) setFloatUniform("falloff", falloff) } + android.graphics.RenderEffect.createRuntimeShaderEffect(shader, "image") + .asComposeRenderEffect() } else { null } diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt b/backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt index 6fffd78..ab5a75c 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.util.lerp @Immutable data class Shadow( - val elevation: Dp = 24f.dp, + val radius: Dp = 24f.dp, val offset: DpOffset = DpOffset(0f.dp, 4f.dp), val color: Color = Color.Black.copy(alpha = 0.15f), val alpha: Float = 1f, @@ -31,7 +31,7 @@ data class Shadow( @Stable fun lerp(start: Shadow, stop: Shadow, fraction: Float): Shadow { return Shadow( - elevation = lerp(start.elevation, stop.elevation, fraction), + radius = lerp(start.radius, stop.radius, fraction), offset = lerp(start.offset, stop.offset, fraction), color = lerp(start.color, stop.color, fraction), alpha = lerp(start.alpha, stop.alpha, fraction), diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt b/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt index a31e807..720feb0 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt @@ -1,30 +1,27 @@ package com.kyant.backdrop.shadow -import android.graphics.Bitmap -import android.graphics.BlendMode -import android.graphics.Canvas -import android.graphics.Color import android.graphics.Paint import android.graphics.PorterDuff import android.graphics.PorterDuffXfermode -import android.graphics.RectF import android.os.Build import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.BlurEffect +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Outline +import androidx.compose.ui.graphics.TileMode import androidx.compose.ui.graphics.asAndroidPath -import androidx.compose.ui.graphics.asComposePaint import androidx.compose.ui.graphics.drawscope.ContentDrawScope import androidx.compose.ui.graphics.drawscope.DrawScope -import androidx.compose.ui.graphics.isUnspecified +import androidx.compose.ui.graphics.drawscope.translate +import androidx.compose.ui.graphics.layer.CompositingStrategy +import androidx.compose.ui.graphics.layer.GraphicsLayer +import androidx.compose.ui.graphics.layer.drawLayer import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.node.DrawModifierNode import androidx.compose.ui.node.ModifierNodeElement -import androidx.compose.ui.node.ObserverModifierNode import androidx.compose.ui.node.invalidateDraw -import androidx.compose.ui.node.observeReads +import androidx.compose.ui.node.requireGraphicsContext import androidx.compose.ui.platform.InspectorInfo import androidx.compose.ui.unit.IntSize import com.kyant.backdrop.ShapeProvider @@ -42,7 +39,7 @@ internal class ShadowElement( override fun update(node: ShadowNode) { node.shapeProvider = shapeProvider node.shadow = shadow - node.invalidateDrawCache() + node.invalidateDraw() } override fun InspectorInfo.inspectableProperties() { @@ -71,92 +68,96 @@ internal class ShadowElement( internal class ShadowNode( var shapeProvider: ShapeProvider, var shadow: () -> Shadow? -) : DrawModifierNode, ObserverModifierNode, Modifier.Node() { +) : DrawModifierNode, Modifier.Node() { override val shouldAutoInvalidate: Boolean = false - private var bitmap: Bitmap? = null - private var canvas: Canvas? = null - private val paint = - Paint().apply { - color = Color.TRANSPARENT - } - private val maskPaint = - Paint().apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - blendMode = BlendMode.CLEAR - } else { - xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) + private var shadowLayer: GraphicsLayer? = null + private var maskLayer: GraphicsLayer? = null + + private val shadowPaint = Paint() + + private var prevRadius = Float.NaN + + override fun ContentDrawScope.draw() { + val shadow = shadow() ?: return drawContent() + + val shadowLayer = shadowLayer + val maskLayer = maskLayer + if (shadowLayer != null && maskLayer != null) { + val size = size + val radius = shadow.radius.toPx() + val offsetX = shadow.offset.x.toPx() + val offsetY = shadow.offset.y.toPx() + val shadowSize = IntSize( + ceil(size.width + radius * 2 + offsetX).toInt(), + ceil(size.height + radius * 2 + offsetY).toInt() + ) + val outline = shapeProvider.shape.createOutline(size, layoutDirection, this) + + configurePaint(shadow) + + if (prevRadius != radius) { + shadowLayer.renderEffect = + if (radius > 0f) { + BlurEffect(radius, radius, TileMode.Decal) + } else { + null + } + prevRadius = radius } - } - private val drawPaint = Paint() - private var prevSize = Size.Unspecified - private var dx = 0f - private var dy = 0f + shadowLayer.record { drawOutline(outline, shadowPaint) } - private var _shadow: Shadow? = null - private var isCacheValid = false - private val cacheDrawBlock: DrawScope.() -> Unit = cacheDrawBlock@{ - val shadow = shadow().also { _shadow = it } - val size = size - if (shadow == null || - shadow.elevation.value <= 0f || shadow.color.isUnspecified || shadow.alpha == 0f - ) { - _shadow = null - return@cacheDrawBlock - } - - val elevation = shadow.elevation.toPx() - val offset = Offset(shadow.offset.x.toPx(), shadow.offset.y.toPx()) - val shadowSize = IntSize( - ceil(size.width + elevation * 2).toInt(), - ceil(size.height + elevation * 2).toInt() - ) - if (shadowSize.width < 0.5f || shadowSize.height < 0.5f) { - _shadow = null - return@cacheDrawBlock - } - - val color = - if (shadow.alpha == 1f) { - shadow.color - } else { - shadow.color.copy(alpha = shadow.color.alpha * shadow.alpha) - } - paint.setShadowLayer(elevation, offset.x, offset.y, color.toArgb()) - drawPaint.asComposePaint().blendMode = shadow.blendMode - - if (prevSize != size) { - bitmap = null - canvas = null - prevSize = size - } - - @Suppress("UseKtx") - val bitmap = - bitmap ?: Bitmap.createBitmap( - shadowSize.width, - shadowSize.height, - Bitmap.Config.ARGB_8888 - ).also { bitmap = it } - val canvas = - canvas?.apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - drawColor(Color.TRANSPARENT, BlendMode.CLEAR) - } else { - drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) + maskLayer.blendMode = shadow.blendMode + maskLayer.record(size = shadowSize) { + translate(radius + offsetX, radius + offsetY) { + drawLayer(shadowLayer) + translate(-offsetX, -offsetY) { + drawOutline(outline, ShadowMaskPaint) + } } - } ?: Canvas(bitmap).also { canvas = it } + } - dx = elevation - offset.x - dy = elevation - offset.y - canvas.translate(dx, dy) + translate(-radius, -radius) { + drawLayer(maskLayer) + } + } - when (val outline = shapeProvider.shape.createOutline(size, layoutDirection, this)) { + drawContent() + } + + override fun onAttach() { + val graphicsContext = requireGraphicsContext() + shadowLayer = graphicsContext.createGraphicsLayer() + maskLayer = + graphicsContext.createGraphicsLayer().apply { + compositingStrategy = CompositingStrategy.Offscreen + } + } + + override fun onDetach() { + val graphicsContext = requireGraphicsContext() + shadowLayer?.let { layer -> + graphicsContext.releaseGraphicsLayer(layer) + shadowLayer = null + } + maskLayer?.let { layer -> + graphicsContext.releaseGraphicsLayer(layer) + maskLayer = null + } + prevRadius = Float.NaN + } + + private fun DrawScope.configurePaint(shadow: Shadow) { + shadowPaint.color = shadow.color.modulate(shadow.alpha).toArgb() + } + + private fun DrawScope.drawOutline(outline: Outline, paint: Paint) { + val canvas = drawContext.canvas.nativeCanvas + + when (outline) { is Outline.Rectangle -> { - val rect = RectF(0f, 0f, size.width, size.height) - canvas.drawRect(rect, paint) - canvas.drawRect(rect, maskPaint) + canvas.drawRect(0f, 0f, size.width, size.height, paint) } is Outline.Rounded -> { @@ -164,46 +165,32 @@ internal class ShadowNode( val path = outline.roundRectPath?.asAndroidPath() if (path != null) { canvas.drawPath(path, paint) - canvas.drawPath(path, maskPaint) } else { - val rect = with(outline.roundRect) { RectF(left, top, right, bottom) } + val rr = outline.roundRect val radius = outline.roundRect.topLeftCornerRadius.x - canvas.drawRoundRect(rect, radius, radius, paint) - canvas.drawRoundRect(rect, radius, radius, maskPaint) + canvas.drawRoundRect(rr.left, rr.top, rr.right, rr.bottom, radius, radius, paint) } } is Outline.Generic -> { val path = outline.path.asAndroidPath() canvas.drawPath(path, paint) - canvas.drawPath(path, maskPaint) } } - - canvas.translate(-dx, -dy) - } - - override fun ContentDrawScope.draw() { - if (!isCacheValid) { - observeReads { cacheDrawBlock() } - isCacheValid = true - } - - val bitmap = bitmap - if (bitmap != null) { - val canvas = drawContext.canvas.nativeCanvas - canvas.drawBitmap(bitmap, -dx, -dy, drawPaint) - } - - drawContent() - } - - override fun onObservedReadsChanged() { - invalidateDrawCache() - } - - fun invalidateDrawCache() { - isCacheValid = false - invalidateDraw() } } + +private val ShadowMaskPaint = Paint().apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + blendMode = android.graphics.BlendMode.CLEAR + } else { + xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) + } +} + +private fun Color.modulate(alpha: Float): Color = + if (alpha != 1.0f) { + copy(alpha = this.alpha * alpha) + } else { + this + } diff --git a/catalog/release/baselineProfiles/0/catalog-release.dm b/catalog/release/baselineProfiles/0/catalog-release.dm index ca630b2..ab4e218 100644 Binary files a/catalog/release/baselineProfiles/0/catalog-release.dm and b/catalog/release/baselineProfiles/0/catalog-release.dm differ diff --git a/catalog/release/baselineProfiles/1/catalog-release.dm b/catalog/release/baselineProfiles/1/catalog-release.dm index 455d76e..0fd3b9e 100644 Binary files a/catalog/release/baselineProfiles/1/catalog-release.dm and b/catalog/release/baselineProfiles/1/catalog-release.dm differ diff --git a/catalog/release/catalog-release.apk b/catalog/release/catalog-release.apk index c4d0870..8b60ace 100644 Binary files a/catalog/release/catalog-release.apk and b/catalog/release/catalog-release.apk differ diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt index 5777fba..62fc250 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt @@ -152,7 +152,7 @@ fun LiquidSlider( }, shadow = { Shadow( - elevation = 4f.dp, + radius = 4f.dp, color = Color.Black.copy(0.05f) ) }, diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt index 5f50202..1af85a7 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt @@ -269,7 +269,7 @@ fun BottomTabsContent() { shadow = { val progress = pressAnimation.value Shadow( - elevation = 24f.dp * progress, + radius = 24f.dp * progress, offset = DpOffset(0f.dp, 4f.dp * progress) ) }, diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt index 51cdeca..e78cb9a 100644 --- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt +++ b/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt @@ -53,7 +53,7 @@ fun LockScreenContent() { }, shadow = { Shadow( - elevation = 4f.dp, + radius = 4f.dp, offset = DpOffset(0f.dp, 1f.dp), color = Color.Black.copy(0.05f) )