How to create an inner shadow with Jetpack Compose? Modifier.shadow()
is just for outer shadows. Using negative elevation is not working.
CodePudding user response:
Position of Modifier.shadow
relative to Modifier.background places shadow inside your component. Also you can create Modifier.drawWithContent and frameworkPaint a show with blur.
Column(
modifier = Modifier
.fillMaxSize()
.padding(20.dp)
) {
ComponentWithInnerShadow()
Spacer(modifier = Modifier.height(12.dp))
ComponentWithOuterShadow()
Spacer(modifier = Modifier.height(12.dp))
ComponentWithCustomInnerShadow()
}
@Composable private fun ComponentWithInnerShadow() {
Column(
modifier = Modifier
.clip(RoundedCornerShape(5.dp))
.background(Color.Yellow)
.shadow(2.dp, shape = RoundedCornerShape(5.dp))
) {
Text(text = "Hello World", modifier = Modifier.padding(12.dp))
} }
@Composable
private fun ComponentWithOuterShadow() {
Column(
modifier = Modifier
.shadow(2.dp, shape = RoundedCornerShape(5.dp))
.background(Color.Yellow)
) {
Text(text = "Hello World", modifier = Modifier.padding(12.dp))
}
}
@Composable
private fun ComponentWithCustomInnerShadow() {
Column(
modifier = Modifier.innerShadow()
) {
Text(text = "Hello World", modifier = Modifier.padding(12.dp))
}
}
And with composed modifier. I didn't set parameters just set arbitrary numbers you can set your own parameters, and set color if you want to. This one looks better than standard inner shadow though. You need to provide color for foreground and shape with this one either. I set color and drew Rounded rectangle for demonstration
fun Modifier.innerShadow() = composed(
inspectorInfo = {
},
factory = {
val paint = remember() {
Paint()
}
val foregroundPaint = remember() {
Paint().apply {
color = Color.Yellow
}
}
val frameworkPaint = remember {
paint.asFrameworkPaint()
}
Modifier.drawWithContent {
this.drawIntoCanvas {
val color = Color.LightGray
val radius = 2.dp.toPx()
val shadowColor = color
.copy(alpha = .7f)
.toArgb()
val transparent = color
.copy(alpha = 0f)
.toArgb()
frameworkPaint.color = transparent
frameworkPaint.setShadowLayer(
radius,
0f,
0f,
shadowColor
)
val shadowRadius = 4.dp.toPx()
it.drawRoundRect(
left = 0f,
top = 0f,
right = this.size.width,
bottom = this.size.height,
radiusX = 5.dp.toPx(),
radiusY = 5.dp.toPx(),
paint = foregroundPaint
)
it.drawRoundRect(
left = 0f,
top = 0f,
right = this.size.width,
bottom = this.size.height,
radiusX = 5.dp.toPx(),
radiusY = 5.dp.toPx(),
paint = paint
)
it.drawRoundRect(
left = shadowRadius,
top = shadowRadius,
right = this.size.width - shadowRadius,
bottom = this.size.height - shadowRadius,
radiusX = 5.dp.toPx(),
radiusY = 5.dp.toPx(),
paint = foregroundPaint
)
drawContent()
}
}
}
)
CodePudding user response:
This is not supported but you have alternative options:
- Use a border modifier with a gradient brush
- Use Android Canvas
- Use a gradient and
Modifier.drawBehind
to draw the inset shadow underneath the content