You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native中实现手指拖拽触发Pressable按钮功能?

React Native实现Pressable拖拽触摸触发功能

当前代码里的Pressable仅在手指首次按下时触发onPressIn,按住第一个按钮拖拽到其他按钮上时,后续按钮不会响应——因为初始触摸事件已被第一个Pressable捕获。要实现拖拽经过时触发按钮状态更新,需要通过父容器跟踪触摸位置,手动判断触摸点落在哪个按钮区域。

修改后的实现代码

import React, { useState, useRef } from "react";
import { View, Text, Pressable } from "react-native";

function Buttons() {
  const [touched, setTouched] = useState(null);
  // 存储每个按钮的ref,用于获取布局位置
  const buttonRefs = {
    a: useRef(null),
    b: useRef(null),
    c: useRef(null),
  };

  // 判断触摸点是否在指定按钮范围内
  const isPointInButton = (point, buttonRef) => {
    if (!buttonRef.current) return false;
    
    let isInside = false;
    buttonRef.current.measureInWindow((x, y, width, height) => {
      const { pageX, pageY } = point;
      // 检查触摸点是否在按钮的坐标范围内
      isInside = pageX >= x && pageX <= x + width && pageY >= y && pageY <= y + height;
    });
    return isInside;
  };

  // 处理触摸开始
  const handleTouchStart = (e) => {
    const touchPoint = e.nativeEvent.pageX ? e.nativeEvent : e.nativeEvent.changedTouches[0];
    Object.entries(buttonRefs).forEach(([key, ref]) => {
      if (isPointInButton(touchPoint, ref)) {
        setTouched(key);
      }
    });
  };

  // 处理触摸移动
  const handleTouchMove = (e) => {
    const touchPoint = e.nativeEvent.pageX ? e.nativeEvent : e.nativeEvent.changedTouches[0];
    let currentTouched = null;
    Object.entries(buttonRefs).forEach(([key, ref]) => {
      if (isPointInButton(touchPoint, ref)) {
        currentTouched = key;
      }
    });
    setTouched(currentTouched);
  };

  // 处理触摸结束
  const handleTouchEnd = () => {
    setTouched(null);
  };

  return (
    <View 
      style={{ flex: 1 }}
      onTouchStart={handleTouchStart}
      onTouchMove={handleTouchMove}
      onTouchEnd={handleTouchEnd}
      onTouchCancel={handleTouchEnd} // 处理触摸被中断的情况
    >
      <Pressable
        ref={buttonRefs.a}
        style={{ flex: 1, margin: 32, backgroundColor: touched === "a" ? "blue" : "red" }}
      >
        <Text style={{ fontSize: 100 }}>a</Text>
      </Pressable>

      <Pressable
        ref={buttonRefs.b}
        style={{ flex: 1, margin: 32, backgroundColor: touched === "b" ? "blue" : "red" }}
      >
        <Text style={{ fontSize: 100 }}>b</Text>
      </Pressable>

      <Pressable 
        ref={buttonRefs.c}
        style={{ flex: 1, margin: 32, backgroundColor: touched === "c" ? "blue" : "red" }}
      >
        <Text style={{ fontSize: 100 }}>c</Text>
      </Pressable>
    </View>
  );
}

export default Buttons;

关键逻辑说明

  • 按钮Ref与布局检测:通过useRef获取每个Pressable实例,用measureInWindow方法获取按钮在屏幕上的坐标范围,判断触摸点是否落在按钮区域内。
  • 触摸事件跟踪:父容器监听onTouchStart、onTouchMove、onTouchEnd事件,实时更新当前触摸的按钮状态。
  • 兼容触摸事件格式:处理原生触摸事件的不同格式(单点触摸时取changedTouches数组第一个元素),确保在不同设备上正常工作。

内容的提问来源于stack exchange,提问作者Blogger Klik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:05:55