dohooo / react-native-reanimated-carousel

🎠 React Native swiper/carousel component, fully implemented using reanimated v2, support to iOS/Android/Web. (Swiper/Carousel)
https://react-native-reanimated-carousel.vercel.app
MIT License
2.86k stars 329 forks source link

No need to specify `height` prop #668

Open 7dp opened 2 months ago

7dp commented 2 months ago

Is your feature request related to a problem? Please describe. I'm always frustrated when this lib requires the height prop. The problem is i can't determine the height of my items. Slightly dynamic, maybe 2 px or 5 px difference between items.

Describe the solution you'd like Just like snap-carousel, no need to specify height prop. The lib will handle it automagically.

Describe alternatives you've considered For now i just rollback to my previous implementation using snap-carousel.

Additional context I hope this very nice lib can handle that in the near future. Thank you so much 🐐. 🙏🔥

dosubot[bot] commented 2 months ago

Hey @7dp! 👋 I'm here to help you with any bugs, questions, or contributions you have for the library. Let's squash those bugs together!

The react-native-reanimated-carousel currently requires the height prop, especially for vertical carousels, to avoid errors. If the height prop is omitted in vertical mode, an error will be thrown [1].

However, you can achieve dynamic height adjustments by using custom animations. Implement a callback function of type TAnimationStyle and pass it to the customAnimation property of the Carousel. This allows you to manipulate the height of items dynamically based on their position [2].

Here's an example:

const animationStyle: TAnimationStyle = React.useCallback((value: number) => {
    'worklet';

    const height = interpolate(value, [-1, 0, 1], [100, 200, 100]); // Adjust heights dynamically

    return {
        height,
    };
}, []);

<Carousel
    style={{ width: screen.width, height: 240 }}
    width={screen.width}
    data={[...new Array(6).keys()]}
    customAnimation={animationStyle}
    renderItem={({ index, animationValue }) => {
        return (
            <CustomItem
                key={index}
                index={index}
                animationValue={animationValue}
            />
        );
    }}
/>;

const CustomItem = ({ index, animationValue }) => {
    const maskStyle = useAnimatedStyle(() => {
        const backgroundColor = interpolateColor(
            animationValue.value,
            [-1, 0, 1],
            ['#000000dd', 'transparent', '#000000dd']
        );

        return {
            backgroundColor,
        };
    }, [animationValue]);

    return (
        <View style={{ flex: 1 }}>
            <SBItem key={index} index={index} style={{ borderRadius: 0 }} />
            <Animated.View
                pointerEvents="none"
                style={[
                    {
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        right: 0,
                        bottom: 0,
                    },
                    maskStyle,
                ]}
            />
        </View>
    );
};

This approach allows for dynamic height adjustments without explicitly setting the height prop for each item.

To continue talking to Dosu, mention @dosu.

7dp commented 2 months ago

My use case is horizontal carousel. Thus, i'm not able to tell explicitly which item that has more/less height than the others. What i want is just like the snap-carousel did.