如何使用 fling 手势向前或向后滑动数组

问题描述 投票:0回答:1

我有一个项目列表,我希望用户能够使用滑动手势进行滑动。当用户向上或向右滑动时,他们将前进到下一个项目(1、2、3 等)。当用户向下或向左滑动时,他们将向后迭代列表(3、2、1 等)。目前,我收到错误 [Reanimated] 尝试在 UI 线程上同步调用非工作集函数“绑定dispatchSetState”。我也尝试过使用 React-Native-Pager-View 和 fling 手势,但也无法完成这项工作。

const Home = props => {
  const theme = useTheme();
  const [currentIndex, setCurrentIndex] = useState(0);
  const getAffirmations = useSelector(state => state.affirmationsSlice);
  const dispatch = useDispatch();
  const getTitles = getAffirmations.affirmations.map(m => {
    return m.title;
  });

  const flingGestureUp = Gesture.Fling()
    .direction(Directions.UP)
    .onEnd(() =>
      setCurrentIndex(prev => (prev + 1) % getAffirmations.affirmations.length),
    );

  const flingGestureDown = Gesture.Fling()
    .direction(Directions.DOWN)
    .onEnd(() => console.log('SwipedDown'));

  const upOrDown = Gesture.Exclusive(flingGestureUp, flingGestureDown);

  return (
    <SafeAreaView>
      <GestureDetector gesture={upOrDown}>
        {/* <PagerView
          initialPage={0}
          orientation={'vertical'}
          onPageScroll={() => handleSwipe()}> */}
        <View style={lightGlobalStyles.affirmationContainer}>
          <Text
            style={[
              lightGlobalStyles.affirmationText,
              theme.theme === true
                ? themes.whiteText
                : theme.theme2 === true
                ? themes.yellowText
                : theme.theme5 === true
                ? themes.darkText
                : themes.offWhiteText,
            ]}>
            {getTitles[currentIndex]}
          </Text>
          <View style={style.makeFavoritePosition}>
            <MakeFavoriteIcon currentIndex={currentIndex} />
          </View>
          <Background />
        </View>
        {/* </PagerView> */}
      </GestureDetector>
    </SafeAreaView>
  );
};

export default Home;
arrays react-native gesture react-native-reanimated
1个回答
0
投票

经过更多研究,这里解决了我的问题。

import {
  Gesture,
  GestureDetector,
  Directions,
} from 'react-native-gesture-handler';
import Animated, {useSharedValue, withTiming} from 'react-native-reanimated';

const Home = props => {
  const theme = useTheme();
  const [currentIndex, setCurrentIndex] = useState(0);
  const getAffirmations = useSelector(state => state.affirmationsSlice);
  const dispatch = useDispatch();
  const getTitles = getAffirmations.affirmations.map(m => {
    return m.title;
  });

  const position = useSharedValue(0);

  const handleUpAndLeft = () => {
    setCurrentIndex(prev => (prev + 1) % getAffirmations.affirmations.length);
  };

  const handleRightAndDown = () => {
    if (currentIndex === 0) {
      setCurrentIndex(getAffirmations.affirmations.length - 1);
    } else {
      setCurrentIndex(prev => (prev - 1) % getAffirmations.affirmations.length);
    }
  };

  const flingGestureRight = Gesture.Fling()
    .runOnJS(true)
    .direction(Directions.RIGHT)
    .onStart(e => {
      position.value = withTiming(position.value + 10, {duration: 100});
      handleRightAndDown();
    });
  const flingGestureUp = Gesture.Fling()
    .runOnJS(true)
    .direction(Directions.UP)
    .onStart(e => {
      position.value = withTiming(position.value + 10, {duration: 100});
      handleUpAndLeft();
    });
  const flingGestureLeft = Gesture.Fling()
    .runOnJS(true)
    .direction(Directions.LEFT)
    .onStart(e => {
      position.value = withTiming(position.value - 10, {duration: 100});
      handleUpAndLeft();
    });
  const flingGestureDown = Gesture.Fling()
    .runOnJS(true)
    .direction(Directions.DOWN)
    .onStart(e => {
      position.value = withTiming(position.value - 10, {duration: 100});
      handleRightAndDown();
    });

  const gestureDirections = Gesture.Exclusive(
    flingGestureLeft,
    flingGestureRight,
    flingGestureUp,
    flingGestureDown,
  );
  return (
    <SafeAreaView>
      <GestureDetector gesture={gestureDirections}>
        <Animated.View style={lightGlobalStyles.affirmationContainer}>
          <Text
            style={[
              lightGlobalStyles.affirmationText,
              theme.theme === true
                ? themes.whiteText
                : theme.theme2 === true
                ? themes.yellowText
                : theme.theme5 === true
                ? themes.darkText
                : themes.offWhiteText,
            ]}>
            {getTitles[currentIndex]}
          </Text>
          <View style={style.makeFavoritePosition}>
            <MakeFavoriteIcon currentIndex={currentIndex} />
          </View>
          <Background />
          </Animated.View>
          </GestureDetector>
        </SafeAreaView>
      );
    };

    export default Home;
© www.soinside.com 2019 - 2024. All rights reserved.