It's actually possible now (they've added more stuff into LazyListState) and it's pretty easy to do. This is a pretty primitive scrollbar (always visible/can't drag/etc) and it uses item indexes to figure out thumb position so it may not look good when scrolling in lists with only few items:
@Composable
fun Modifier.simpleVerticalScrollbar(
state: LazyListState,
width: Dp = 8.dp
): Modifier {
val targetAlpha = if (state.isScrollInProgress) 1f else 0f
val duration = if (state.isScrollInProgress) 150 else 500
val alpha by animateFloatAsState(
targetValue = targetAlpha,
animationSpec = tween(durationMillis = duration)
)
return drawWithContent {
drawContent()
val firstVisibleElementIndex = state.layoutInfo.visibleItemsInfo.firstOrNull()?.index
val needDrawScrollbar = state.isScrollInProgress || alpha > 0.0f
// Draw scrollbar if scrolling or if the animation is still running and lazy column has content
if (needDrawScrollbar && firstVisibleElementIndex != null) {
val elementHeight = this.size.height / state.layoutInfo.totalItemsCount
val scrollbarOffsetY = firstVisibleElementIndex * elementHeight
val scrollbarHeight = state.layoutInfo.visibleItemsInfo.size * elementHeight
drawRect(
color = Color.Red,
topLeft = Offset(this.size.width - width.toPx(), scrollbarOffsetY),
size = Size(width.toPx(), scrollbarHeight),
alpha = alpha
)
}
}
}
UPD:
I've updated the code. I've figured out how to show/hide scrollbar when LazyColumn is being scrolled or not + added fade in/out animation. I also changed drawBehind() to drawWithContent() because the former draws behind the content so it may probably draw on top of the scrollbar in some cases which is most likely not desireable.