Add scrollbar desing for android on MyVerticalScrollbar
This commit is contained in:
parent
c06053c5dc
commit
ffb6a4c080
1 changed files with 107 additions and 4 deletions
|
|
@ -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
|
||||||
){
|
) {
|
||||||
|
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()
|
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))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue