Add scrollbar desing for android on MyVerticalScrollbar

This commit is contained in:
Hasinjato 2026-06-23 11:33:38 +03:00
parent c06053c5dc
commit ffb6a4c080

View file

@ -1,16 +1,119 @@
package mg.dot.feufaro.ui package mg.dot.feufaro.ui
import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@Composable @Composable
actual fun MyVerticalScrollbar ( actual fun MyVerticalScrollbar(
modifier: Modifier, modifier: Modifier,
scrollState: ScrollState?, scrollState: ScrollState?,
lazyListState: LazyListState?, lazyListState: LazyListState?,
content: @Composable () -> Unit content: @Composable () -> Unit
){ ) {
content() val coroutineScope = rememberCoroutineScope()
val density = LocalDensity.current
var containerHeight by remember { mutableStateOf(1f) }
val thumbHeight = 75.dp
val scrollPercentage by remember(scrollState, lazyListState) {
derivedStateOf {
if (scrollState != null && scrollState.maxValue > 0) {
scrollState.value.toFloat() / scrollState.maxValue
} else if (lazyListState != null) {
val layoutInfo = lazyListState.layoutInfo
val totalItems = layoutInfo.totalItemsCount
if (totalItems == 0) 0f else {
val firstVisibleItem = lazyListState.firstVisibleItemIndex
firstVisibleItem.toFloat() / totalItems
}
} else {
0f
}
}
}
Box(
modifier = modifier.onGloballyPositioned { coordinates ->
containerHeight = coordinates.size.height.toFloat()
}
) {
content()
Box(
modifier = Modifier
.align(Alignment.CenterEnd)
.fillMaxHeight()
.width(15.dp)
.background(Color.Transparent)
) {
val thumbHeightPx = with(density) { thumbHeight.toPx() }
val maxOffset = containerHeight - thumbHeightPx
val currentThumbOffset = (scrollPercentage * maxOffset).coerceIn(0f, maxOffset.coerceAtLeast(0f))
Box(
modifier = Modifier
.offset(y = with(density) { currentThumbOffset.toDp() })
.width(10.dp)
.height(thumbHeight)
.align(Alignment.TopEnd)
.clip(RoundedCornerShape(5.dp))
.background(
brush = Brush.verticalGradient(
colors = listOf(
MaterialTheme.colorScheme.secondary.copy(alpha = 1f),
MaterialTheme.colorScheme.secondary.copy(alpha = 0.75f),
MaterialTheme.colorScheme.secondary.copy(alpha = 0.5f)
)
)
)
.draggable(
orientation = Orientation.Vertical,
state = rememberDraggableState { delta ->
coroutineScope.launch {
if (maxOffset > 0) {
val scrollRatio = delta / maxOffset
if (scrollState != null) {
scrollState.scrollBy(scrollRatio * scrollState.maxValue)
} else if (lazyListState != null) {
val totalItems = lazyListState.layoutInfo.totalItemsCount
lazyListState.scrollBy(scrollRatio * totalItems * 120f)
}
}
}
}
)
) {
Box(
modifier = Modifier
.align(Alignment.TopCenter)
.padding(top = 4.dp)
.size(6.dp)
.blur(1.dp)
.background(MaterialTheme.colorScheme.background, RoundedCornerShape(3.dp))
)
}
}
}
} }