Skip to content

Instantly share code, notes, and snippets.

@sproctor
Last active February 17, 2024 19:34
Show Gist options
  • Save sproctor/297103451bdcdd25eef5b233a0d7af56 to your computer and use it in GitHub Desktop.
Save sproctor/297103451bdcdd25eef5b233a0d7af56 to your computer and use it in GitHub Desktop.
ScrollableColumn and LazyScrollableColumn for Compose for desktop
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.Constraints
import kotlin.math.max
@Composable
actual fun ScrollableLazyColumnImpl(
modifier: Modifier,
state: LazyListState,
contentPadding: PaddingValues,
reverseLayout: Boolean,
verticalArrangement: Arrangement.Vertical,
horizontalAlignment: Alignment.Horizontal,
flingBehavior: FlingBehavior,
userScrollEnabled: Boolean,
content: LazyListScope.() -> Unit
) {
ScrollableWrapper(modifier) {
LazyColumn(
state = state,
contentPadding = contentPadding,
reverseLayout = reverseLayout,
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
content = content,
)
VerticalScrollbar(adapter = rememberScrollbarAdapter(state))
}
}
@Composable
actual fun ScrollableColumnImpl(
modifier: Modifier,
state: ScrollState,
verticalArrangement: Arrangement.Vertical,
horizontalAlignment: Alignment.Horizontal,
contentPadding: PaddingValues,
content: @Composable ColumnScope.() -> Unit
) {
ScrollableWrapper(modifier) {
Column(
modifier = Modifier
.padding(contentPadding)
.verticalScroll(state),
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
content = content,
)
VerticalScrollbar(adapter = rememberScrollbarAdapter(state))
}
}
@Composable
private fun ScrollableWrapper(modifier: Modifier, content: @Composable () -> Unit) {
Layout(
content = content,
modifier = modifier,
) { measurables, constraints ->
val columnPlaceable = measurables[0].measure(constraints)
val scrollbarPlaceable = measurables[1].measure(
Constraints(
minHeight = columnPlaceable.height,
maxHeight = columnPlaceable.height,
maxWidth = constraints.maxWidth,
)
)
layout(columnPlaceable.width, columnPlaceable.height) {
columnPlaceable.place(0, 0)
scrollbarPlaceable.place(max(0, columnPlaceable.width - scrollbarPlaceable.width), 0)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment