diff --git a/example/src/App.tsx b/example/src/App.tsx index d5929d4..0b92335 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -9,7 +9,7 @@ */ import React from 'react'; -import { StyleSheet, View, Image } from 'react-native'; +import { StyleSheet, View, Image, Dimensions } from 'react-native'; import Carousel from '@r0b0t3d/react-native-carousel'; const data = [ @@ -58,16 +58,18 @@ const data = [ }, ]; +const { width } = Dimensions.get('window'); + export default function App() { return ( { return ( { - const viewSize = e.layoutMeasurement; // Divide the horizontal offset by the width of the view to see which page is visible - const page = e.contentOffset.x / viewSize.width; + const page = e.contentOffset.x / itemWidth; const leftPage = Math.round(page); const rightPage = leftPage + 1; const diff = 0.2; @@ -76,6 +77,7 @@ function Carousel( } else if (rightPage - page <= diff) { pageNum = rightPage; } + console.log('refreshPage', pageNum, currentPage); if (pageNum !== currentPage) { if (expectedPosition.current === pageNum) { freeze.value = false; @@ -100,6 +102,8 @@ function Carousel( const handleScrollTo = useCallback( (page: number, animated = true) => { + console.log('handleScrollTo', page); + const to = page * sliderWidth; if (getRef()) { getRef().scrollTo({ x: to, y: 0, animated }); @@ -109,10 +113,12 @@ function Carousel( ); useEffect(() => { - setTimeout(() => { - handleScrollTo(currentPage, false); - freeze.value = false; - }); + if (currentPage !== 0) { + setTimeout(() => { + handleScrollTo(currentPage, false); + freeze.value = false; + }); + } }, []); const jumpTo = useCallback( @@ -199,11 +205,28 @@ function Carousel( style={styles.container} horizontal showsHorizontalScrollIndicator={false} - pagingEnabled - scrollEventThrottle={16} + snapToInterval={itemWidth} + snapToAlignment={'center'} decelerationRate="fast" + scrollEventThrottle={16} onScroll={scrollHandler} bounces={false} + // iOS ONLY + contentInset={ + firstItemAlignment === 'center' + ? { + top: 0, + left: (sliderWidth - itemWidth) / 2, // Left spacing for the very first card + bottom: 0, + right: (sliderWidth - itemWidth) / 2, // Right spacing for the very last card + } + : {} + } + contentContainerStyle={{ + // contentInset alternative for Android + paddingHorizontal: + Platform.OS === 'android' ? (sliderWidth - itemWidth) / 2 : 0, // Horizontal spacing before and after the ScrollView + }} {...{ scrollViewProps }} > {pageItems.map((item, i) => ( @@ -211,6 +234,7 @@ function Carousel( key={`${item.id}-${i}`} item={item} index={i} + itemWidth={itemWidth} animatedValue={animatedScroll} animation={animation} renderImage={renderImage} diff --git a/src/components/PageItem.tsx b/src/components/PageItem.tsx index 818d3bc..bad0030 100644 --- a/src/components/PageItem.tsx +++ b/src/components/PageItem.tsx @@ -1,11 +1,9 @@ import React from 'react'; -import { Dimensions, Image, StyleSheet, View } from 'react-native'; +import { Image, StyleSheet, View } from 'react-native'; import type Animated from 'react-native-reanimated'; import { withParallax } from '../animators/parrallax'; import type { CarouselData } from '../types'; -const { width: wWidth } = Dimensions.get('window'); - type Props = { item: CarouselData; index: number; @@ -14,6 +12,7 @@ type Props = { animatedValue: Animated.SharedValue; animation?: 'parallax'; freeze: Animated.SharedValue; + itemWidth: number; }; export default function PageItem({ @@ -24,6 +23,7 @@ export default function PageItem({ animatedValue, animation, freeze, + itemWidth, }: Props) { function renderContent() { if (renderImage) { @@ -57,7 +57,7 @@ export default function PageItem({ ; animation?: 'parallax'; sliderWidth?: number; + itemWidth?: number; + firstItemAlignment?: 'start' | 'center' renderIndicator?: (props: { selected: boolean; index: number;