Alexander Maryanovsky
12/18/2023, 11:41 AMAlexander Maryanovsky
12/18/2023, 11:42 AM/**
* Draws a top-shadow, proportional (but capped) to the scrolled value.
*/
@Composable
fun ScrollShadow(
scrollState: ScrollState,
modifier: Modifier
) {
val elevation by remember(scrollState) {
derivedStateOf { (scrollState.value/2).coerceAtMost(3).dp }
}
Box(
modifier
.height(1.dp)
.offset(y = (-1).dp)
.clip(OpenBottomShape)
.shadow(elevation)
)
}
/**
* A shape that clips the box such that only the shadow at the bottom is drawn.
*/
private val OpenBottomShape = GenericShape { size, _ ->
moveTo(size.width, size.height)
lineTo(size.width, Float.MAX_VALUE)
lineTo(0f, Float.MAX_VALUE)
lineTo(0f, size.height)
}
fun main() = singleWindowApplication {
Column {
Text("Header", Modifier.padding(24.dp), style = TextStyle(fontWeight = FontWeight.Bold))
Box(Modifier.fillMaxSize()) {
val scrollState = rememberScrollState()
ScrollShadow(scrollState, Modifier.fillMaxWidth())
Column(Modifier.verticalScroll(scrollState).fillMaxWidth()) {
repeat(20) {
Text("Item $it", Modifier.padding(16.dp))
}
}
VerticalScrollbar(rememberScrollbarAdapter(scrollState), Modifier.align(Alignment.CenterEnd))
}
}
}
Alexander Maryanovsky
12/18/2023, 11:42 AMSamson Jisso
12/18/2023, 1:19 PM