feat: 任务切换加滑动动画 + 严格手势防误触

1. 手势判断从 dx>dy 改为 dx>dy*2 且 dx>80px,斜滑不再误触
2. 切换任务时内容滑出+滑入动画(120ms出+150ms入),有明确感知

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-05-07 17:42:00 +09:30
parent 3d991c0169
commit 7b5ad64fea

View File

@@ -92,19 +92,17 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
findNavController().popBackStack() findNavController().popBackStack()
} }
// 左右滑手势(切换任务),上下滑留给内容滚动 // 左右滑手势(切换任务),严格区分水平/垂直防误触
gestureDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() { gestureDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() {
override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
if (e1 == null) return false if (e1 == null) return false
val dy = e2.y - e1.y val dy = e2.y - e1.y
val dx = e2.x - e1.x val dx = e2.x - e1.x
// 水平滑动且幅度 > 垂直 // 水平幅度必须 > 垂直的 2 倍,且 > 80px防止斜滑误触
if (abs(dx) > abs(dy) && abs(dx) > 50) { if (abs(dx) > abs(dy) * 2 && abs(dx) > 80) {
if (dx < 0) { if (dx < 0) {
// 左滑 → 下一个任务
nextTask() nextTask()
} else { } else {
// 右滑 → 上一个任务
prevTask() prevTask()
} }
return true return true
@@ -212,22 +210,46 @@ class TaskListFragment : BaseFragment<FragmentTaskListBinding>() {
// ===== 左右滑切换 ===== // ===== 左右滑切换 =====
/** 下一个任务(左滑) */ /** 下一个任务(左滑,内容从右滑入 */
private fun nextTask() { private fun nextTask() {
if (taskIndex < taskList.size - 1) { if (taskIndex < taskList.size - 1) {
taskIndex++ taskIndex++
fetchCurrentDetail() animateSwitch(fromRight = true)
} }
} }
/** 上一个任务(右滑) */ /** 上一个任务(右滑,内容从左滑入 */
private fun prevTask() { private fun prevTask() {
if (taskIndex > 0) { if (taskIndex > 0) {
taskIndex-- taskIndex--
fetchCurrentDetail() animateSwitch(fromRight = false)
} }
} }
/** 切换任务时的滑入动画 */
private fun animateSwitch(fromRight: Boolean) {
val content = binding.scrollView
val screenWidth = content.width.toFloat()
// 旧内容滑出
val slideOut = if (fromRight) -screenWidth else screenWidth
content.animate()
.translationX(slideOut)
.alpha(0f)
.setDuration(120)
.withEndAction {
// 加载新数据
fetchCurrentDetail()
// 新内容从另一边滑入
content.translationX = if (fromRight) screenWidth else -screenWidth
content.animate()
.translationX(0f)
.alpha(1f)
.setDuration(150)
.start()
}
.start()
}
// ===== UI 显示 ===== // ===== UI 显示 =====
/** /**