1

The shadow is clipping in a very odd way when it's overlapping other items in a LazyRow and I can't figure out why. I'm running this code on TV emulator but I can't imagine that would make any difference.

Attempt 1: Modifier.shadow()

val colors = listOf(
    Color.Red,
    Color.Blue,
    Color.Green,
    Color.Yellow
)

@Composable
fun ListTest() {
    LazyColumn {
        items(30) {
            Column {
                Text("This is row $it")
                LazyRow {
                    items(colors) {
                        var isFocused by remember { mutableStateOf(false) }
                        val alpha = if (isFocused) 1f else 0.25f
                        val elevation = if (isFocused) 40.dp else 0.dp
                        Surface(
                            shape = RoundedCornerShape(8.dp),
                            color = it.copy(alpha = alpha),
                            modifier = Modifier
                                .width(240.dp)
                                .height(150.dp)
                                .padding(start = 16.dp)
                                //  Look here
                                .shadow(elevation)
                                .onFocusChanged { state ->
                                    isFocused = state.isFocused
                                }
                                .focusable(),
                        ) {
                           // Content here
                        }
                    }
                }
            }
        }
    }
}

Image showing shadow clipping issue

Attempt 2: Modifier.drawBehind {}

I was referred to these lines in the Android code that limits elevation to 30.dp.


val colors = listOf(
    Color.Red,
    Color.Blue,
    Color.Green,
    Color.Yellow
)

@Composable
fun ListTest() {
    LazyColumn {
        items(30) {
            Column {
                Text("This is row $it")
                LazyRow {
                    items(colors) {
                        var isFocused by remember { mutableStateOf(false) }
                        val alpha = if (isFocused) 1f else 0.25f
                        val shadowColor = if (isFocused) Color.Black else Color.Transparent
                        Surface(
                            shape = RoundedCornerShape(8.dp),
                            color = it.copy(alpha = alpha),
                            modifier = Modifier
                                .width(240.dp)
                                .height(150.dp)
                                .padding(start = 16.dp)
                                //  Look here
                                .coloredShadow(shadowColor)
                                .onFocusChanged { state ->
                                    isFocused = state.isFocused
                                }
                                .focusable(),
                        ) {
                            // Content here
                        }
                    }
                }
            }
        }
    }
}


fun Modifier.coloredShadow(color: Color) = drawBehind {
    val shadowColor = color.toArgb()
    val transparentColor = color.copy(alpha = 0f).toArgb()
    val offsetX = 0.dp
    val offsetY = 8.dp
    val cornerRadius = 4.dp
    drawIntoCanvas {
        val paint = Paint()
        val frameworkPaint = paint.asFrameworkPaint()
        frameworkPaint.color = transparentColor
        frameworkPaint.setShadowLayer(
            //  Set to 400.dp as radius
            400.dp.toPx(), 
            offsetX.toPx(),
            offsetY.toPx(),
            shadowColor
        )
        it.drawRoundRect(
            0f,
            0f,
            this.size.width,
            this.size.height,
            cornerRadius.toPx(),
            cornerRadius.toPx(),
            paint
        )
    }
}

Image showing shadow clipping issue after 2nd attempt

How can I get rid of this clipping issue?

vighnesh153
  • 4,354
  • 2
  • 13
  • 27
Jonas Borggren
  • 2,591
  • 1
  • 22
  • 40

1 Answers1

0

I don't think it's a clipping issue. You just have the elevation set too high, so the surface's shadow has to reach across another row/column, and display on top of another Surface, but because they're not children of the same view, it's not processing the shadow blurring properly.

Maybe you should try setting the elevation to 30dp or 24dp?

user496854
  • 6,461
  • 10
  • 47
  • 84
  • This is true, that's what I'm trying to achieve. I want it much larger than it is now, and I don't see why that would be impossible when it's already overlapping other items but just a little. I should've added what I want to achieve I guess, but what I want to achieve is a much larger shadow than what is there now. – Jonas Borggren Oct 07 '22 at 07:35
  • I'm actually not sure if that's a bug, or if that's how shadows are supposed to work. Like I said, you're basically "spilling" the shadow outside of it's container view. You would need to file a bug report in Google's Compose issue tracker, and see what they tell you – user496854 Oct 07 '22 at 11:39
  • It definitely feels like there should be a way to do this without making all of the views children of the same parent. Looks like there are a lot of issues in the Compose issue tracker about shadows getting clipped. Seems like a tricky problem and several of the issues are marked as "Won't Fix (Working As Intended)". – Clark Sandholtz Apr 07 '23 at 20:34