Skip to content

Instantly share code, notes, and snippets.

@L10n42
Last active May 14, 2024 14:26
Show Gist options
  • Save L10n42/475e25365cfde757f40a66cadbec3eaa to your computer and use it in GitHub Desktop.
Save L10n42/475e25365cfde757f40a66cadbec3eaa to your computer and use it in GitHub Desktop.
Inner Shadow in Jetpack Compose
import android.graphics.BlurMaskFilter
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
/**
* Adds an inner shadow effect to the content.
*
* @param shape The shape of the shadow.
* @param color The color of the shadow.
* @param blur The blur radius of the shadow.
* @param offsetY The shadow offset along the Y-axis.
* @param offsetX The shadow offset along the X-axis.
* @param spread The spread of the inner shadow.
*
* @return A modified Modifier with the inner shadow effect applied.
*/
fun Modifier.innerShadow(
shape: Shape,
color: Color = Color.Black,
blur: Dp = 4.dp,
offsetY: Dp = 1.dp,
offsetX: Dp = 1.dp,
spread: Dp = 0.dp
) = drawWithContent {
drawContent()
val rect = Rect(Offset.Zero, size)
val paint = Paint().apply {
this.color = color
this.isAntiAlias = true
}
val shadowOutline = shape.createOutline(size, layoutDirection, this)
drawIntoCanvas { canvas ->
canvas.saveLayer(rect, paint)
canvas.drawOutline(shadowOutline, paint)
val frameworkPaint = paint.asFrameworkPaint()
frameworkPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
if (blur.toPx() > 0) {
frameworkPaint.maskFilter = BlurMaskFilter(blur.toPx(), BlurMaskFilter.Blur.NORMAL)
}
paint.color = Color.Black
val spreadOffsetX = offsetX.toPx() + if (offsetX.toPx() < 0) -spread.toPx() else spread.toPx()
val spreadOffsetY = offsetY.toPx() + if (offsetY.toPx() < 0) -spread.toPx() else spread.toPx()
canvas.translate(spreadOffsetX, spreadOffsetY)
canvas.drawOutline(shadowOutline, paint)
canvas.restore()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment