fix: 下拉手势改用RecyclerView.OnItemTouchListener
SwipeDownLayout的onInterceptTouchEvent方案仍无法检测到下拉。 改用ViewPager2内部RecyclerView的addOnItemTouchListener, 这是RecyclerView专门提供的触摸观察接口,在RecyclerView 处理事件之前通知listener,保证能看到所有触摸事件。 使用rawY避免坐标系问题,阈值60px(约45dp@120dpi)。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,12 @@ package com.xiaoqu.watch.ui.home
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@@ -145,10 +147,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
showRevokeConfirm()
|
showRevokeConfirm()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 面板关闭时恢复 ViewPager2 滑动和下拉检测
|
// 面板关闭时恢复 ViewPager2 滑动
|
||||||
punchPanel.onDismiss = {
|
punchPanel.onDismiss = {
|
||||||
binding.viewPager.isUserInputEnabled = true
|
binding.viewPager.isUserInputEnabled = true
|
||||||
binding.swipeDownLayout.swipeEnabled = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,9 +205,8 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
/** 展开打卡面板 */
|
/** 展开打卡面板 */
|
||||||
private fun showPunchPanel() {
|
private fun showPunchPanel() {
|
||||||
if (punchPanel.isShowing) return
|
if (punchPanel.isShowing) return
|
||||||
// 禁用 ViewPager2 滑动和下拉检测
|
// 禁用 ViewPager2 滑动
|
||||||
binding.viewPager.isUserInputEnabled = false
|
binding.viewPager.isUserInputEnabled = false
|
||||||
binding.swipeDownLayout.swipeEnabled = false
|
|
||||||
// 查询考勤状态
|
// 查询考勤状态
|
||||||
punchViewModel.fetchAttendance()
|
punchViewModel.fetchAttendance()
|
||||||
// 展开面板
|
// 展开面板
|
||||||
@@ -215,17 +215,51 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
|
|
||||||
// ===== 下拉手势 =====
|
// ===== 下拉手势 =====
|
||||||
|
|
||||||
|
/** 触摸起始 Y */
|
||||||
|
private var touchStartY = 0f
|
||||||
|
/** 触摸起始 X */
|
||||||
|
private var touchStartX = 0f
|
||||||
|
/** 本次手势是否已触发过下拉 */
|
||||||
|
private var swipeTriggered = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化下拉手势检测
|
* 初始化下拉手势检测
|
||||||
* 使用 SwipeDownLayout 在 onInterceptTouchEvent 中检测下拉
|
* 通过 RecyclerView.OnItemTouchListener 监听 ViewPager2 内部触摸
|
||||||
* 比 setOnTouchListener 更可靠——能在事件被子 View 消费前看到
|
* 这是最可靠的方式——RecyclerView 在处理事件前会先通知所有 listener
|
||||||
*/
|
*/
|
||||||
private fun initSwipeDownDetector() {
|
private fun initSwipeDownDetector() {
|
||||||
binding.swipeDownLayout.onSwipeDown = {
|
// ViewPager2 内部 RecyclerView 需等布局完成后获取
|
||||||
// 只在主页(page=1)且面板未展开时响应
|
binding.viewPager.post {
|
||||||
if (binding.viewPager.currentItem == 1 && !punchPanel.isShowing) {
|
val recyclerView = binding.viewPager.getChildAt(0) as? RecyclerView
|
||||||
showPunchPanel()
|
recyclerView?.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
||||||
}
|
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
|
||||||
|
when (e.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
touchStartY = e.rawY
|
||||||
|
touchStartX = e.rawX
|
||||||
|
swipeTriggered = false
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
if (swipeTriggered) return false
|
||||||
|
// 只在主页(page=1)且面板未展开时响应
|
||||||
|
if (binding.viewPager.currentItem != 1) return false
|
||||||
|
if (punchPanel.isShowing) return false
|
||||||
|
|
||||||
|
val dy = e.rawY - touchStartY
|
||||||
|
val dx = e.rawX - touchStartX
|
||||||
|
// 下滑超过 60px 且方向以垂直为主
|
||||||
|
if (dy > 60 && Math.abs(dy) > Math.abs(dx) * 1.5f) {
|
||||||
|
swipeTriggered = true
|
||||||
|
showPunchPanel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
swipeTriggered = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false // 不拦截,ViewPager2 正常工作
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user