Skip to content

Instantly share code, notes, and snippets.

@bhavin-android
Forked from Andrew0000/ComposeShadow.kt
Created October 11, 2024 06:04
Show Gist options
  • Save bhavin-android/cb876793704b3e22b638a08059c9d19d to your computer and use it in GitHub Desktop.
Save bhavin-android/cb876793704b3e22b638a08059c9d19d to your computer and use it in GitHub Desktop.
Jetpack Compose custom shadow with dx, dy and radius
import android.graphics.BlurMaskFilter
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@Preview(
widthDp = 160,
heightDp = 160,
showBackground = true,
backgroundColor = 0xffffff,
)
@Composable
private fun Preview() {
Box(
modifier = Modifier
.requiredSize(100.dp)
.background(Color.Yellow),
) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(25.dp)
.shadowCustom(
offsetX = 8.dp,
offsetY = 8.dp,
blurRadius = 8.dp,
),
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Green),
) {
}
}
}
}
fun Modifier.shadowCustom(
color: Color = Color.Black,
offsetX: Dp = 0.dp,
offsetY: Dp = 0.dp,
blurRadius: Dp = 0.dp,
shapeRadius: Dp = 0.dp,
) = composed {
val paint: Paint = remember { Paint() }
val blurRadiusPx = blurRadius.px(LocalDensity.current)
val maskFilter = remember {
BlurMaskFilter(blurRadiusPx, BlurMaskFilter.Blur.NORMAL)
}
drawBehind {
drawIntoCanvas { canvas ->
val frameworkPaint = paint.asFrameworkPaint()
if (blurRadius != 0.dp) {
frameworkPaint.maskFilter = maskFilter
}
frameworkPaint.color = color.toArgb()
val leftPixel = offsetX.toPx()
val topPixel = offsetY.toPx()
val rightPixel = size.width + leftPixel
val bottomPixel = size.height + topPixel
if (shapeRadius > 0.dp) {
val radiusPx = shapeRadius.toPx()
canvas.drawRoundRect(
left = leftPixel,
top = topPixel,
right = rightPixel,
bottom = bottomPixel,
radiusX = radiusPx,
radiusY = radiusPx,
paint = paint,
)
} else {
canvas.drawRect(
left = leftPixel,
top = topPixel,
right = rightPixel,
bottom = bottomPixel,
paint = paint,
)
}
}
}
}
private fun Dp.px(density: Density): Float =
with(density) { toPx() }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment