https://kotlinlang.org logo
#compose
Title
# compose
w

wintersoldier

01/19/2023, 7:12 AM
I wanted to add shadow to a composable. Shadow should be only applied to the top. (Not required for left or right). Is there some way to achieve this. Code snippet I already tried,
Copy code
Box(
  modifier = Modifier
    .background(Color.Yellow)
    .shadow(
      elevation = 2.dp,
    ),
) {
content()
}
o

Oleksandr Balan

01/19/2023, 7:38 AM
You could use
drawWithContent
modifier to clip the content as you need. For example recently I create a custom modifier which is uses
drawWithContent
inside:
Copy code
fun Modifier.clipSides(
    left: Boolean = true,
    top: Boolean = true,
    right: Boolean = true,
    bottom: Boolean = true
): Modifier = drawWithContent {
    clipRect(
        left = if (left) 0f else -Float.MAX_VALUE,
        top = if (top) 0f else -Float.MAX_VALUE,
        right = if (right) size.width else Float.MAX_VALUE,
        bottom = if (bottom) size.height else Float.MAX_VALUE,
    ) {
        this@drawWithContent.drawContent()
    }
}
Thus you can use it on your Box to clip only sides you need:
Copy code
Box(
  modifier = Modifier
    .background(Color.Yellow)
    .shadow(elevation = 2.dp)
    .clipSides(top = false, bottom = false),
) {
content()
}
w

wintersoldier

01/19/2023, 9:04 AM
I have tried this approach , If you see the screenshot the shadow is getting applied on top , left and right
Copy code
Box(
  modifier = Modifier
    .background(Color.Yellow)
    .shadow(elevation = 2.dp)
    .clipSides(top = false, bottom = false),
) {
content()
}
I have used this code exactly
o

Oleksandr Balan

01/19/2023, 9:29 AM
Oops, true I used it on
Surface
:
Copy code
Surface(
    shadowElevation = 8.dp,
    color = Color.Yellow,
    modifier = Modifier.clipSides(top = false, bottom = false),
) {
    Button(
        onClick = { /* Empty */ },
        modifier = Modifier.padding(16.dp)
    ) {
        Text(text = "Test")
    }
}
w

wintersoldier

01/19/2023, 10:32 AM
This works , But one problem I have noticed is if I set shadow(elevation) to Box its more visible. Whereas in case of surface if I apply elevation its not really that visible
Have you faced a similar issue?
o

Oleksandr Balan

01/19/2023, 10:58 AM
Looks pretty same to me 🧐 Maybe it’s because you have swapped modifiers order? Shadow should go before background I guess
Copy code
Row(
    verticalAlignment = Alignment.CenterVertically,
    horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally),
    modifier = Modifier.fillMaxSize()
) {
    Surface(
        shadowElevation = 2.dp,
        color = Color.Yellow,
    ) {
        Button(
            onClick = { /* Empty */ },
            modifier = Modifier.padding(16.dp)
        ) {
            Text(text = "Test")
        }
    }
    Box(
        modifier = Modifier
            .shadow(2.dp)
            .background(Color.Yellow)
    ) {
        Button(
            onClick = { /* Empty */ },
            modifier = Modifier.padding(16.dp)
        ) {
            Text(text = "Test")
        }
    }
}
w

wintersoldier

01/19/2023, 11:05 AM
Its the same code I have also executed . But in the
Surface
can't find a param called
shadowElevation
like you shared above. All I can find is
elevation
. Will that be the issue😕, other than that Its exactly the same code I have written
o

Oleksandr Balan

01/19/2023, 11:15 AM
Mine
Surface
comes from Material3 library, yours if from Material2. Just tried it with M2
Surface
and it looks same to me 😅
w

wintersoldier

01/19/2023, 11:26 AM
In the first screenshot, I have used Box where shadow is much more visible (but clip is not getting applied). In second screenshot I have used surface , I can find the shadow but its very much less compared to the first one.
o

Oleksandr Balan

01/19/2023, 11:30 AM
Seems like you have wrong modifiers order on your Box 🤔 Do you use
Copy code
Box(
  modifier = Modifier
    .background(...)
    .shadow(elevation = 2.dp)
)
or
Copy code
Box(
  modifier = Modifier
    .shadow(elevation = 2.dp)
    .background(...)
)
? The last should behave as
Surface
, because
Surface
is literally a Box 😄
w

wintersoldier

01/19/2023, 11:54 AM
You are right , the last one is behaving similar to surface where as the first one is adding more visible elevation(but on all sides)
75 Views