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