feat: improve media picker bottom sheet

This commit is contained in:
k1ngsterr1
2026-02-02 02:37:10 +05:00
parent 5e5c2af494
commit 78a8bfe6de

View File

@@ -264,35 +264,68 @@ fun MediaPickerBottomSheet(
} }
// Функция snap к ближайшему состоянию с плавной анимацией // Функция snap к ближайшему состоянию с плавной анимацией
fun snapToNearestState() { // Используем velocity для определения направления
fun snapToNearestState(velocity: Float = 0f) {
animationScope.launch { animationScope.launch {
val currentHeight = sheetHeightPx.value val currentHeight = sheetHeightPx.value
val midPoint = (collapsedHeightPx + expandedHeightPx) / 2
// Пороги основаны на velocity (скорости свайпа) - не на позиции!
// velocity < 0 = свайп вверх, velocity > 0 = свайп вниз
val velocityThreshold = 300f // Маленький порог для лёгкого свайпа
when { when {
// Слишком низко - закрываем // Быстрый свайп вниз при минимальной высоте - закрываем
currentHeight < minHeightPx + 50 -> { velocity > velocityThreshold && currentHeight < collapsedHeightPx -> {
animatedClose() animatedClose()
} }
// Ближе к expanded // Слишком низко - закрываем
currentHeight > midPoint -> { currentHeight < minHeightPx + 30 -> {
animatedClose()
}
// Быстрый свайп вверх - разворачиваем
velocity < -velocityThreshold -> {
isExpanded = true isExpanded = true
sheetHeightPx.animateTo( sheetHeightPx.animateTo(
expandedHeightPx, expandedHeightPx,
animationSpec = spring( animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy, dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMedium stiffness = Spring.StiffnessMediumLow
)
)
}
// Быстрый свайп вниз - сворачиваем (или закрываем если уже свёрнут)
velocity > velocityThreshold -> {
if (isExpanded) {
isExpanded = false
sheetHeightPx.animateTo(
collapsedHeightPx,
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMediumLow
)
)
} else {
animatedClose()
}
}
// Без velocity - snap к ближайшему
currentHeight > (collapsedHeightPx + expandedHeightPx) / 2 -> {
isExpanded = true
sheetHeightPx.animateTo(
expandedHeightPx,
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMediumLow
) )
) )
} }
// Ближе к collapsed
else -> { else -> {
isExpanded = false isExpanded = false
sheetHeightPx.animateTo( sheetHeightPx.animateTo(
collapsedHeightPx, collapsedHeightPx,
animationSpec = spring( animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy, dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMedium stiffness = Spring.StiffnessMediumLow
) )
) )
} }
@@ -364,6 +397,9 @@ fun MediaPickerBottomSheet(
val currentHeightDp = with(density) { sheetHeightPx.value.toDp() } val currentHeightDp = with(density) { sheetHeightPx.value.toDp() }
val slideOffset = (sheetHeightPx.value * animatedOffset).toInt() val slideOffset = (sheetHeightPx.value * animatedOffset).toInt()
// Отслеживаем velocity для плавного snap
var lastDragVelocity by remember { mutableFloatStateOf(0f) }
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -385,12 +421,17 @@ fun MediaPickerBottomSheet(
.pointerInput(Unit) { .pointerInput(Unit) {
detectVerticalDragGestures( detectVerticalDragGestures(
onDragEnd = { onDragEnd = {
// Snap к ближайшему состоянию // Snap с учётом velocity
snapToNearestState() snapToNearestState(lastDragVelocity)
lastDragVelocity = 0f
}, },
onVerticalDrag = { change, dragAmount -> onVerticalDrag = { change, dragAmount ->
change.consume() change.consume()
// 🔥 КЛЮЧЕВОЕ: Меняем высоту в реальном времени! // Сохраняем velocity (dragAmount в пикселях)
// Усиливаем чувствительность в 1.5 раза
lastDragVelocity = dragAmount * 1.5f
// 🔥 Меняем высоту в реальном времени
val newHeight = (sheetHeightPx.value - dragAmount) val newHeight = (sheetHeightPx.value - dragAmount)
.coerceIn(minHeightPx, expandedHeightPx) .coerceIn(minHeightPx, expandedHeightPx)
animationScope.launch { animationScope.launch {