fix: 下拉手势改用Activity.dispatchTouchEvent检测

前两种方案(SwipeDownLayout.onInterceptTouchEvent、
RecyclerView.OnItemTouchListener)均无法检测到下拉。

改用Activity.dispatchTouchEvent——触摸事件链最顶层,
在任何View处理之前就能看到所有触摸事件,不可能被拦截。

HomeFragment注册回调,onDestroyView时清理避免泄漏。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-04-28 21:13:46 +09:30
parent 68f3b2d890
commit b274012019
2 changed files with 51 additions and 43 deletions

View File

@@ -2,6 +2,7 @@ package com.xiaoqu.watch.app
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
@@ -10,6 +11,7 @@ import com.xiaoqu.watch.service.manager.SystemStateMonitor
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
import javax.inject.Inject
import kotlin.math.abs
/**
* 主 ActivityLauncher 模式,单 Activity + 多 Fragment 架构)
@@ -54,6 +56,43 @@ class MainActivity : AppCompatActivity() {
systemStateMonitor.unregister()
}
// ===== 下拉手势检测Activity 级别,不可能被子 View 拦截) =====
/** 下拉回调(由 HomeFragment 注册) */
var onSwipeDown: (() -> Unit)? = null
private var touchStartY = 0f
private var touchStartX = 0f
private var swipeTriggered = false
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
// 在事件分发给任何 View 之前,先检测下拉手势
if (onSwipeDown != null) {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
touchStartY = ev.rawY
touchStartX = ev.rawX
swipeTriggered = false
}
MotionEvent.ACTION_MOVE -> {
if (!swipeTriggered) {
val dy = ev.rawY - touchStartY
val dx = ev.rawX - touchStartX
// 下滑超过 50px 且垂直方向为主
if (dy > 50 && abs(dy) > abs(dx) * 1.5f) {
swipeTriggered = true
onSwipeDown?.invoke()
}
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
swipeTriggered = false
}
}
}
return super.dispatchTouchEvent(ev)
}
/**
* 物理返回键拦截:
* - 已绑定用户 → 开启 NFC 打卡模式(后续模块实现)