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