scrollIndicator
A modifier that draws and handles interactions for a scroll indicator (e.g., a scrollbar) defined
scrollIndicator
Compose Modifier
Common
fun Modifier.scrollIndicator(
factory: ScrollIndicatorFactory,
state: ScrollIndicatorState,
orientation: Orientation,
): Modifier
A modifier that draws and handles interactions for a scroll indicator (e.g., a scrollbar) defined
by the provided factory.
The ScrollIndicatorFactory is responsible for creating the UI and behavior of the indicator,
while the state provides the necessary data, like scroll offset and content size, to correctly
represent the scroll position.
Parameters
| factory | The ScrollIndicatorFactory that creates the scroll indicator. |
| state | The ScrollIndicatorState for the scrollable component. |
| orientation | The scrolling orientation of the container. The indicator will be drawn and interact based on this orientation. |
Code Examples
VisualScrollbarSample
@Composable
fun VisualScrollbarSample() {
// A basic implementation of ScrollIndicator that draws a simple visual scrollbar.
data class BasicVisualScrollbarFactory(
val thumbThickness: Dp = 8.dp,
val padding: Dp = 4.dp,
val thumbColor: Color = Color.Gray,
val thumbAlpha: Float = 0.5f,
) : ScrollIndicatorFactory {
// The node is the core of the ScrollIndicator, handling the drawing logic.
override fun createNode(
state: ScrollIndicatorState,
orientation: Orientation,
): DelegatableNode {
return object : Modifier.Node(), DrawModifierNode {
override fun ContentDrawScope.draw() {
// Draw the original content.
drawContent()
// Don't draw the scrollbar if the content fits within the viewport.
if (state.contentSize <= state.viewportSize) return
val visibleContentRatio = state.viewportSize.toFloat() / state.contentSize
// Calculate the thumb's size and position along the scrolling axis.
val thumbLength = state.viewportSize * visibleContentRatio
val thumbPosition = state.scrollOffset * visibleContentRatio
val thumbThicknessPx = thumbThickness.toPx()
val paddingPx = padding.toPx()
// Determine the scrollbar size and thumb position based on the orientation.
val (topLeft, size) =
when (orientation) {
Orientation.Vertical -> {
val x = size.width - thumbThicknessPx - paddingPx
Offset(x, thumbPosition) to Size(thumbThicknessPx, thumbLength)
}
Orientation.Horizontal -> {
val y = size.height - thumbThicknessPx - paddingPx
Offset(thumbPosition, y) to Size(thumbLength, thumbThicknessPx)
}
}
// Draw the scrollbar thumb.
drawRect(color = thumbColor, topLeft = topLeft, size = size, alpha = thumbAlpha)
}
}
}
}
val scrollState = rememberScrollState()
val scrollbarFactory = remember { BasicVisualScrollbarFactory() }
val scrollbarModifier =
scrollState.scrollIndicatorState?.let {
Modifier.scrollIndicator(
factory = scrollbarFactory,
state = it,
orientation = Orientation.Vertical,
)
} ?: Modifier
Column(modifier = Modifier.fillMaxSize().then(scrollbarModifier).verticalScroll(scrollState)) {
repeat(50) { Text(text = "Item ${it + 1}", modifier = Modifier.padding(8.dp)) }
}
}