繁体   English   中英

PanResponder - 在另一个组件上调用 Animated.spring 后重置手势状态

PanResponder - gestureState reset after calling Animated.spring on another component

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在 React Native 中设置一个拖放图像添加栏。 前提是用户可以拖动图像(在单行中)以重新排列它们,或者将它们拖动到行左侧的垃圾桶中。

我对所有图像(最多 5 个)使用单个 panResponder。 平移响应器获取目标并相应地设置位置。

但是,如果我使用Animated.spring在 onPanResponderMove 方法中移动不同的组件,则当前被拖动的组件会立即重置为其原始 position。

For instance, if I move item c to the left one index, Animated.spring gets called on item b moving it to the right 1 index (60px), however when that happens item c gets forced back to its original position (now over item b的当前位置),因为gestureState.dx突然再次报告0。

为什么会发生这种情况,我该如何解决这个问题?

到目前为止我所拥有的:

import React, { useState, useEffect, useMemo, useRef } from 'react';
import {
  TouchableOpacity,
  View,
  Image,
  Text,
  Animated,
  PanResponder,
} from 'react-native';

interface AddImageBarProps {
  onImageAdd: () => void;
  onImageRemove: () => void;
}

const addImage = require('../../../Assets/img/OtherActionButtons/addPhoto.png');
const trash = require('../../../Assets/img/OtherActionButtons/trash.png');

export const AddImageBar = (props: AddImageBarProps) => {
  const width = 50;
  const margin = 5;

  const imageRefs = useRef([]);
  const positionRefs = useRef([]);

  const [imageArr, setImageArr] = useState<string[]>(['a', 'b', 'c']);
  const [deleteMode, setDeleteMode] = useState(false);
  const [moving, setMoving] = useState<boolean[]>([]);

  useEffect(() => {
    positionRefs.current = [];
    for (let i = 0; i < imageArr.length; i++) {
      positionRefs.current = [...positionRefs.current, new Animated.ValueXY()];
    }
  }, [imageArr]);

  const findIndex = (eventTarget: string) => {
    const index = imageRefs.current.findIndex((imgRef) => {
      return imgRef?._nativeTag === eventTarget;
    });
    if (index >= 0) {
      return index;
    }
    return undefined;
  };

  const getMovedIndexes = (dx: number): number => {
    let indexCount = 0;
    const dxIsNeg = dx < 0;
    if (dxIsNeg) {
      dx = dx * -1;
    }

    dx = dx - width / 2 - margin;
    if (dx < 0) {
      return;
    }
    indexCount = indexCount + 1;
    indexCount = indexCount + Math.trunc(dx / (width + margin));

    return dxIsNeg ? indexCount * -1 : indexCount;
  };

  const updateMoving = (i: number, value: boolean) => {
    const newMoving = moving.map((item, index) => {
      if (index === i) {
        return value;
      } else {
        return item;
      }
    });
    setMoving(newMoving);
  };

  const panResponder = useMemo(
    () =>
      PanResponder.create({
        onStartShouldSetPanResponder: (event, gestureState) => true,
        onPanResponderMove: (event, gestureState) => {
          const index = findIndex(event.nativeEvent.target);
          positionRefs.current[index].setValue({
            x: gestureState.dx,
            y: gestureState.dy,
          });

          const movedIndex = getMovedIndexes(gestureState.dx);

          if (index > 0 && movedIndex < 0) {
            console.log(`movedIndex: `, JSON.stringify(movedIndex));
            for (let i = movedIndex; i < 0; i++) {
              if (!moving[index + i]) {
                console.log(`index + i: `, JSON.stringify(index + i));
                updateMoving(index + i, true);
                Animated.spring(positionRefs.current[0], {
                  toValue: { x: width + margin, y: 0 },
                  friction: 10,
                  useNativeDriver: true,
                }).start(() => {
                  updateMoving(index + i, false);
                });
              }
            }
          }
        },
        onPanResponderGrant: (event) => {
          setDeleteMode(true);
          console.log(`granting`);
        },
        onPanResponderRelease: (event, gestureState) => {
          console.log(`releasing`);
          setDeleteMode(false);
        },
      }),
    [moving],
  );

  return (
    <View
      style={{ marginVertical: 5, flexDirection: 'row', alignItems: 'center' }}>
      <TouchableOpacity
        style={{ borderWidth: 1, borderColor: '#a1a1a1', borderRadius: 3 }}>
        <Image
          source={deleteMode ? trash : addImage}
          resizeMode="contain"
          style={{
            height: 50,
            width: 50,
          }}
        />
      </TouchableOpacity>
      {imageArr.map((item, index) => {
        return (
          <Animated.View
            ref={(element) =>
              (imageRefs.current = [...imageRefs.current, element])
            }
            key={index}
            style={{
              backgroundColor: '#0FF',
              height: 50,
              width: 50,
              justifyContent: 'center',
              alignItems: 'center',
              marginHorizontal: 5,
              transform: [
                {
                  translateX: positionRefs.current[index]?.x
                    ? positionRefs.current[index].x
                    : 0,
                },
                { translateY: 0 },
              ],
            }}
            {...panResponder.panHandlers}>
            <View pointerEvents="none">
              <Text>{item}</Text>
            </View>
          </Animated.View>
        );
      })}
    </View>
  );
};
问题暂未有回复.您可以查看右边的相关问题.
3 在UIButton上调用默认手势?

我的view上有一个自定义UIButton 。 您是否知道在首次加载按钮时(例如在willMoveToSuperview期间或在viewDidLoad )是否为此按钮调用了任何“默认”操作? 例如,也许调用了UIControlEventTouchUpInside事件? 或其他事件? ...

4 State 似乎没有在 Animated.spring() 中更新

我正在尝试使用功能组件制作类似滑动功能的火种。 我基本上制作了以下教程的功能版本 https://www.instamobile.io/react-native-controls/react-native-swipe-cards-tinder/ 但是我遇到了一个奇怪的问题,显示卡的 state 似乎 ...

5 Animated.spring完成事件

我试图弄清楚Animated.spring事件何时完成,以便我可以更新一些状态。 我已经尝试过了,但是在这里完成抛出未定义的错误; 还有其他方法可以解决吗? 谢谢 ...

7 在轻击手势上调用UIISlider valueChanged方法

我有一个UISlider的子类,它连接到故事板上以进行valueChanged: 在我的子类viewDidLoad中,我得到了: 然后在同一个子类中,一个不错的点击处理程序将滑块移动并更新当前值: 没关系,设置值,然后继续生活。 但是,唯一的问题是,视图控制器中的Sto ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM