Open sohuichoi opened 2 months ago
Your issue with the react-native-reanimated-carousel
not scrolling horizontally on a real device when using the vertical-stack
mode can be resolved by using the fixedDirection
API. This API ensures that the carousel scrolls in a consistent direction.
Here's how you can modify your code to use the fixedDirection
API:
import React from 'react';
import { Text, View } from 'react-native';
import Carousel from 'react-native-reanimated-carousel';
const CustomCarousel = () => {
const [currentImageIndex, setCurrentImageIndex] = React.useState(0);
const data = [1, 2, 3, 4, 5];
const baseOptions = {
width: 300,
height: 232,
} as const;
return (
<Carousel
{...baseOptions}
style={{
width: 400,
height: 400,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
}}
data={[1, 2, 3, 4, 5].reverse()}
defaultIndex={4}
windowSize={3}
scrollAnimationDuration={500}
onSnapToItem={(index) => setCurrentImageIndex(index)}
pagingEnabled={true}
onProgressChange={(_, absoluteProgress) => {
setCurrentImageIndex(Math.round(absoluteProgress));
}}
onConfigurePanGesture={(panGesture) => {
panGesture.activeOffsetX([-50, 50]);
}}
loop
mode='vertical-stack'
modeConfig={{
snapDirection: 'right',
stackInterval: -30,
scaleInterval: 0.1,
rotateZDeg: 5,
}}
fixedDirection="horizontal" // Add this line
renderItem={({ item, index }) => {
const colors = ['#FFB3BA', '#BAFFC9', '#BAE1FF', '#FFFFBA', '#FFD8B1'];
const backgroundColor = colors[index % colors.length];
return (
<View
style={{
height: 320,
width: 320,
backgroundColor,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Text
style={{
fontSize: 40,
}}
>
{item}
</Text>
</View>
);
}}
/>
);
};
export default CustomCarousel;
This should ensure that the carousel scrolls horizontally even when using the vertical-stack mode [1].
To continue talking to Dosu, mention @dosu.
@dosu It still doesn't work. When I swipe horizontally, the View scroll down sometimes.
To fix the issue where the react-native-reanimated-carousel
in vertical-stack
mode scrolls down sometimes when swiped horizontally, even after using the fixedDirection
API, you need to ensure that the fixedDirection
is correctly applied during the gesture updates and end events.
Here is the relevant part of the code where fixedDirection
is applied:
const onGestureUpdate = useCallback((e: PanGestureHandlerEventPayload) => {
"worklet";
if (validStart.value) {
validStart.value = false;
cancelAnimation(translation);
}
touching.value = true;
const { translationX, translationY } = e;
let panTranslation = isHorizontal.value
? translationX
: translationY;
if (fixedDirection === "negative")
panTranslation = -Math.abs(panTranslation);
else if (fixedDirection === "positive")
panTranslation = +Math.abs(panTranslation);
if (!loop) {
if ((translation.value > 0 || translation.value < -max.value)) {
const boundary = translation.value > 0 ? 0 : -max.value;
const fixed = boundary - panOffset.value;
const dynamic = panTranslation - fixed;
translation.value = boundary + dynamic * 0.5;
return;
}
}
const translationValue = panOffset.value + panTranslation;
translation.value = translationValue;
}, [
isHorizontal,
max,
panOffset,
loop,
overscrollEnabled,
fixedDirection,
translation,
validStart,
touching,
]);
const onGestureEnd = useCallback((e: GestureStateChangeEvent<PanGestureHandlerEventPayload>, _success: boolean) => {
"worklet";
const { velocityX, velocityY, translationX, translationY } = e;
const scrollEndVelocityValue = isHorizontal.value
? velocityX
: velocityY;
scrollEndVelocity.value = scrollEndVelocityValue;
let panTranslation = isHorizontal.value
? translationX
: translationY;
if (fixedDirection === "negative")
panTranslation = -Math.abs(panTranslation);
else if (fixedDirection === "positive")
panTranslation = +Math.abs(panTranslation);
scrollEndTranslation.value = panTranslation;
const totalTranslation = scrollEndVelocityValue + panTranslation;
if (
maxScrollDistancePerSwipeIsSet && Math.abs(totalTranslation) > maxScrollDistancePerSwipe
) {
const nextPage = Math.round((panOffset.value + maxScrollDistancePerSwipe * Math.sign(totalTranslation)) / size) * size;
translation.value = withSpring(withProcessTranslation(nextPage), onScrollEnd);
}
else if (
minScrollDistancePerSwipeIsSet && Math.abs(totalTranslation) < minScrollDistancePerSwipe
) {
const nextPage = Math.round((panOffset.value + minScrollDistancePerSwipe * Math.sign(totalTranslation)) / size) * size;
translation.value = withSpring(withProcessTranslation(nextPage), onScrollEnd);
}
else {
endWithSpring(panTranslation, scrollEndVelocityValue, onScrollEnd);
}
if (!loop)
touching.value = false;
}, [
size,
loop,
touching,
panOffset,
translation,
isHorizontal,
scrollEndVelocity,
scrollEndTranslation,
fixedDirection,
maxScrollDistancePerSwipeIsSet,
maxScrollDistancePerSwipe,
minScrollDistancePerSwipe,
endWithSpring,
withSpring,
onScrollEnd,
]);
Ensure that the fixedDirection
logic is correctly applied and that the translation
value is being updated appropriately based on the direction constraints. If the issue persists, you may need to debug further to ensure that the fixedDirection
is being respected throughout the gesture handling process [1].
To continue talking to Dosu, mention @dosu.
Describe the bug I set the vertical-stack carousel which is swipped by horizontal gesture. But in the real device, the carousel cannot scroll horizontally well, like the attached file. To Reproduce Steps to reproduce the behavior: the following code is what I develop.
Expected behavior A clear and concise description of what you expected to happen. I want the scroll animation works well. Screenshots If applicable, add screenshots to help explain your problem.
https://github.com/user-attachments/assets/537f624f-a1e2-4eed-8dc8-0f60913bdc2f
Versions (please complete the following information):
Smartphone (please complete the following information):
Additional context Add any other context about the problem here.