From 2bfc9f8110f41b96581aabffe5f75d38b867c81a Mon Sep 17 00:00:00 2001 From: Developer Date: Wed, 25 Mar 2026 13:28:49 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B0=8F=E7=AA=97?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8B=96=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit onStartShouldSetPanResponder 被内部 TouchableOpacity 抢占响应权。 改用 onMoveShouldSetPanResponderCapture:位移 >3px 时从子组件夺回响应权, 点击仍正常透传到 TouchableOpacity。 --- components/LiveMiniPlayer.tsx | 14 +++++++++++--- components/MiniPlayer.tsx | 11 +++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/components/LiveMiniPlayer.tsx b/components/LiveMiniPlayer.tsx index 9be127c..4237f30 100644 --- a/components/LiveMiniPlayer.tsx +++ b/components/LiveMiniPlayer.tsx @@ -35,7 +35,14 @@ export function LiveMiniPlayer() { const panResponder = useRef( PanResponder.create({ - onStartShouldSetPanResponder: () => true, + // 不在 start 阶段抢夺,让 TouchableOpacity 的点击正常触发 + onStartShouldSetPanResponder: () => false, + onStartShouldSetPanResponderCapture: () => false, + // 有实际位移时,从子组件夺回响应权(capture 阶段,优先于子组件) + onMoveShouldSetPanResponder: (_, { dx, dy }) => + Math.abs(dx) > 3 || Math.abs(dy) > 3, + onMoveShouldSetPanResponderCapture: (_, { dx, dy }) => + Math.abs(dx) > 3 || Math.abs(dy) > 3, onPanResponderGrant: () => { pan.setOffset({ x: (pan.x as any)._value, y: (pan.y as any)._value }); pan.setValue({ x: 0, y: 0 }); @@ -51,12 +58,10 @@ export function LiveMiniPlayer() { const curY = (pan.y as any)._value; // 吸附到左边缘或右边缘(取最近的一侧) - // container 默认 right:12,pan.x=0 为右侧,-(sw-MINI_W-24) 为左侧贴边 const snapRight = 0; const snapLeft = -(sw - MINI_W - 24); const snapX = curX < snapLeft / 2 ? snapLeft : snapRight; - // Y 轴仅做越界回弹,不吸附 const clampedY = Math.max(-sh + MINI_H + 60, Math.min(60, curY)); Animated.spring(pan, { @@ -66,6 +71,9 @@ export function LiveMiniPlayer() { friction: 10, }).start(); }, + onPanResponderTerminate: () => { + pan.flattenOffset(); + }, }), ).current; diff --git a/components/MiniPlayer.tsx b/components/MiniPlayer.tsx index a1a307e..0d01f56 100644 --- a/components/MiniPlayer.tsx +++ b/components/MiniPlayer.tsx @@ -20,7 +20,12 @@ export function MiniPlayer() { const panResponder = useRef( PanResponder.create({ - onStartShouldSetPanResponder: () => true, + onStartShouldSetPanResponder: () => false, + onStartShouldSetPanResponderCapture: () => false, + onMoveShouldSetPanResponder: (_, { dx, dy }) => + Math.abs(dx) > 3 || Math.abs(dy) > 3, + onMoveShouldSetPanResponderCapture: (_, { dx, dy }) => + Math.abs(dx) > 3 || Math.abs(dy) > 3, onPanResponderGrant: () => { pan.setOffset({ x: (pan.x as any)._value, y: (pan.y as any)._value }); pan.setValue({ x: 0, y: 0 }); @@ -32,7 +37,6 @@ export function MiniPlayer() { const curX = (pan.x as any)._value; const curY = (pan.y as any)._value; - // 吸附到左边缘或右边缘(取最近的一侧) const snapRight = 0; const snapLeft = -(sw - MINI_W - 24); const snapX = curX < snapLeft / 2 ? snapLeft : snapRight; @@ -46,6 +50,9 @@ export function MiniPlayer() { friction: 10, }).start(); }, + onPanResponderTerminate: () => { + pan.flattenOffset(); + }, }) ).current;