我有一个项目列表,我希望用户能够使用滑动手势进行滑动。当用户向上或向右滑动时,他们将前进到下一个项目(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;
经过更多研究,这里解决了我的问题。
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;