I want to make rounded corner with shadow for my card view. I am trying to make look like this
I am trying in Box
with the help of Modifier
Using shadow
and clip
with ordering like this
Box(
modifier = Modifier
.fillMaxSize()
.shadow(1.dp)
.clip(RoundedCornerShape(12.dp))
.padding(
start = 16.dp,
end = 16.dp,
top = 12.dp,
bottom = 16.dp,
)
) {
// method in here
}
and it looks like this
Now I changed to order like this clip
and shadow
Box(
modifier = Modifier
.fillMaxSize()
.clip(RoundedCornerShape(12.dp))
.shadow(1.dp)
.padding(
start = 16.dp,
end = 16.dp,
top = 12.dp,
bottom = 16.dp,
)
) {
// method in here
}
and it look like this
I don't understand ordering of modifier now. Can anyone guide me on this ?
TL;DR Use only Modifier.shadow(elevation, shape) which also clips based on shadow elevation.
@Stable
fun Modifier.shadow(
elevation: Dp,
shape: Shape = RectangleShape,
clip: Boolean = elevation > 0.dp,
ambientColor: Color = DefaultShadowColor,
spotColor: Color = DefaultShadowColor,
)
Before understanding order of Modifiers i think it's better to explain what Modifier.shadow does and how it works.
Modifier.shadow is basically a transparent background(see first sample where no background is assigned) and border around your Composable with some blur effect. If you draw it without a background you will have rectangle with blur based on elevation and spot color and order of it depends if it will be drawn behind or in front of your Composable.
@Preview
@Composable
private fun ShadowSample() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Shadow Order")
Box(
modifier = Modifier
.size(100.dp)
.shadow(
elevation = 10.dp,
spotColor = Color.Red,
shape = RoundedCornerShape(8.dp)
),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
Spacer(modifier = Modifier.height(20.dp))
Box(
modifier = Modifier
.background(Color.Red)
.size(100.dp)
.shadow(
elevation = 10.dp,
shape = RoundedCornerShape(8.dp)
),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
Spacer(modifier = Modifier.height(20.dp))
Box(
modifier = Modifier
.shadow(
elevation = 10.dp,
shape = RoundedCornerShape(8.dp)
)
.background(Color.Red)
.size(100.dp),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
}
}
First one is how it is without any background. In second one shadow is drawn after background so it's drawn in front of your Composable like drawing a border or Rect in front of it.
Modifier.clip clips everything out of your Composable your border including any drawing(without clip you can draw anything out of your Composable) or shadow in our example as in example below
In first example we clip shadow and border that's why you don't see any shadow and green Rectangle border is clipped with rounded rectangle shape.
In second example shadow is before clip so it's not clipped but green border is.
In third example since border is before Modifier.shadow it's not clipped, as you can see it has rectangle shape. But anything after Modifier.shadow is clipped because Modifier.shadow comes with clip param true.
@Preview
@Composable
private fun ShadowSample2(){
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Clipping with Shadow")
Box(
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.shadow(
elevation = 10.dp,
RoundedCornerShape(8.dp)
)
.border(1.dp, Color.Green)
.background(Color.White)
.size(100.dp),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
Spacer(modifier = Modifier.height(10.dp))
Box(
modifier = Modifier
.shadow(
elevation = 10.dp,
shape = RoundedCornerShape(8.dp)
)
.clip(RoundedCornerShape(8.dp))
.border(1.dp, Color.Green)
.background(Color.White)
.size(100.dp),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
Spacer(modifier = Modifier.height(10.dp))
Box(
modifier = Modifier
.border(1.dp, Color.Green)
.shadow(
elevation = 10.dp,
shape = RoundedCornerShape(8.dp)
)
.background(Color.White)
.size(100.dp),
contentAlignment = Alignment.Center
) {
Text("Hello World")
}
}
}