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

View File

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