feat: improve media picker bottom sheet
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user