Fix collapse drag not tracking finger — use dynamic dragRange based on actual height change

The fixed DRAG_RANGE_DP=200dp caused the collapse progress to advance faster
than the visual height change, making the calendar feel like it "outruns" the
finger. Now dragRangePx is computed as (weeks-1)×rowHeight, matching the
actual visual height delta during collapse so finger movement maps 1:1 to
visual change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-15 16:29:24 +08:00
parent 73d42902ea
commit d0492d02f0
3 changed files with 18 additions and 10 deletions

View File

@ -16,7 +16,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import plus.rua.project.CalendarViewModel import plus.rua.project.CalendarViewModel
@ -24,16 +23,16 @@ import plus.rua.project.CalendarViewModel
* 底部卡片折叠状态下支持垂直拖拽触发折叠动画 * 底部卡片折叠状态下支持垂直拖拽触发折叠动画
* *
* @param viewModel 日历 ViewModel用于读取折叠状态和驱动拖拽 * @param viewModel 日历 ViewModel用于读取折叠状态和驱动拖拽
* @param dragRangePx 拖拽手势映射范围像素progress 01 对应手指移动此距离
* 应设为折叠时日历实际高度变化量 (weeks-1)×rowHeight使拖拽跟手
* @param modifier 外部布局修饰符 * @param modifier 外部布局修饰符
*/ */
@Composable @Composable
fun BottomCard( fun BottomCard(
viewModel: CalendarViewModel, viewModel: CalendarViewModel,
dragRangePx: Float,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val density = LocalDensity.current
val dragRange = with(density) { DRAG_RANGE_DP.dp.toPx() }
Surface( Surface(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
@ -48,7 +47,7 @@ fun BottomCard(
viewModel.onExpandDragEnd() viewModel.onExpandDragEnd()
} }
) { _, dragAmount -> ) { _, dragAmount ->
val delta = -dragAmount / dragRange val delta = -dragAmount / dragRangePx
viewModel.onExpandDrag(delta) viewModel.onExpandDrag(delta)
} }
} else { } else {
@ -61,7 +60,7 @@ fun BottomCard(
viewModel.onDragEnd() viewModel.onDragEnd()
} }
) { _, dragAmount -> ) { _, dragAmount ->
val delta = -dragAmount / dragRange val delta = -dragAmount / dragRangePx
viewModel.onDrag(delta) viewModel.onDrag(delta)
} }
} }
@ -82,4 +81,4 @@ fun BottomCard(
) )
} }
} }
} }

View File

@ -180,9 +180,18 @@ fun CalendarMonthView(
} }
} }
if (cardHeightPx > 0) { // 拖拽范围 = 折叠时日历实际高度变化量 (weeks-1)×rowHeight使手指移动与视觉变化 1:1 对应
val dragRangeMinPx = with(density) { DRAG_RANGE_MIN_DP.dp.toPx() }
val dragRangePx = if (effectiveRowHeightPx > 0) {
maxOf((effectiveWeeks - 1) * effectiveRowHeightPx.toFloat(), dragRangeMinPx)
} else {
dragRangeMinPx
}
if (cardHeightPx > 0) {
BottomCard( BottomCard(
viewModel = viewModel, viewModel = viewModel,
dragRangePx = dragRangePx,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(with(density) { cardHeightPx.toDp() }) .height(with(density) { cardHeightPx.toDp() })

View File

@ -21,8 +21,8 @@ const val ROW_PADDING_DP = 6
/** 日历网格水平 padding (dp) */ /** 日历网格水平 padding (dp) */
const val HORIZONTAL_PADDING_DP = 16 const val HORIZONTAL_PADDING_DP = 16
/** BottomCard 拖拽手势范围 (dp) */ /** BottomCard 拖拽手势范围最小值 (dp),防止行数少时 dragRange 过小 */
const val DRAG_RANGE_DP = 200 const val DRAG_RANGE_MIN_DP = 100
/** 日历与 BottomCard 之间的间距 (dp):展开时 */ /** 日历与 BottomCard 之间的间距 (dp):展开时 */
const val CARD_GAP_EXPANDED_DP = 24 const val CARD_GAP_EXPANDED_DP = 24