React Native wrapper for Android and iOS ViewPager
—
React hook for managing PagerView state, animations, and programmatic control with React Native Reanimated integration. Provides a comprehensive interface for building interactive pager experiences with smooth animations.
Main hook providing stateful management of PagerView with animation support and programmatic controls.
/**
* Hook for managing PagerView state, animations, and programmatic control
* @param params - Configuration object with pagesAmount
* @returns Complete interface for PagerView management
*/
function usePagerView(params?: UsePagerViewParams): UsePagerViewProps;
interface UsePagerViewParams {
/** Initial number of pages to create. Default: 0 */
pagesAmount: number;
}
interface UsePagerViewProps {
/** Ref object for the PagerView component */
ref: React.MutableRefObject<PagerView | null>;
/** Current active page index */
activePage: number;
/** Whether page transitions are animated */
isAnimated: boolean;
/** Array of page indices */
pages: number[];
/** Current scroll state */
scrollState: 'idle' | 'dragging' | 'settling';
/** Whether scrolling is enabled */
scrollEnabled: boolean;
/** Current scroll progress with position and offset */
progress: { position: number; offset: number };
/** Whether overdrag is enabled */
overdragEnabled: boolean;
/** Navigate to specific page (respects animation setting) */
setPage: (page: number) => void;
/** Add a new page to the end */
addPage: () => void;
/** Remove the last page */
removePage: () => void;
/** Toggle scroll enabled state */
toggleScroll: () => void;
/** Toggle animation enabled state */
toggleAnimation: () => void;
/** Toggle overdrag enabled state */
toggleOverdrag: () => void;
/** Set progress state manually */
setProgress: React.Dispatch<React.SetStateAction<{ position: number; offset: number }>>;
/** Animated event handler for page scroll */
onPageScroll: Animated.Event<PagerViewOnPageScrollEventData>;
/** Animated event handler for page selection */
onPageSelected: Animated.Event<PagerViewOnPageSelectedEventData>;
/** Scroll state change handler */
onPageScrollStateChanged: (e: PageScrollStateChangedNativeEvent) => void;
/** Animated version of PagerView component */
AnimatedPagerView: React.ComponentType<PagerViewProps>;
/** Reference to PagerView component class */
PagerView: typeof PagerView;
}Basic Usage Example:
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { usePagerView } from 'react-native-pager-view';
export default function BasicHookExample() {
const {
ref,
activePage,
pages,
setPage,
addPage,
removePage,
PagerView,
} = usePagerView({ pagesAmount: 3 });
return (
<View style={styles.container}>
<View style={styles.controls}>
<Text>Active Page: {activePage}</Text>
<View style={styles.buttonRow}>
<Button title="Previous" onPress={() => setPage(Math.max(0, activePage - 1))} />
<Button title="Next" onPress={() => setPage(Math.min(pages.length - 1, activePage + 1))} />
</View>
<View style={styles.buttonRow}>
<Button title="Add Page" onPress={addPage} />
<Button title="Remove Page" onPress={removePage} />
</View>
</View>
<PagerView ref={ref} style={styles.pagerView} initialPage={0}>
{pages.map((pageIndex) => (
<View style={styles.page} key={pageIndex}>
<Text style={styles.text}>Page {pageIndex + 1}</Text>
</View>
))}
</PagerView>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
controls: { padding: 20, backgroundColor: '#f0f0f0' },
buttonRow: {
flexDirection: 'row',
justifyContent: 'space-around',
marginVertical: 10
},
pagerView: { flex: 1 },
page: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#e0e0e0',
},
text: { fontSize: 24, fontWeight: 'bold' },
});Advanced animation features with React Native Reanimated integration for smooth, native-feeling transitions.
/** Animated version of PagerView with Reanimated support */
const AnimatedPagerView: React.ComponentType<PagerViewProps>;
/** Animated event handler for scroll events */
const onPageScroll: Animated.Event<{
nativeEvent: {
offset: Animated.Value;
position: Animated.Value;
};
}>;
/** Animated event handler for page selection events */
const onPageSelected: Animated.Event<{
nativeEvent: {
position: Animated.Value;
};
}>;Animation Usage Example:
import React from 'react';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
import Animated, {
useAnimatedStyle,
interpolate,
Extrapolate
} from 'react-native-reanimated';
import { usePagerView } from 'react-native-pager-view';
const { width } = Dimensions.get('window');
export default function AnimatedExample() {
const {
ref,
pages,
progress,
onPageScroll,
onPageSelected,
AnimatedPagerView,
} = usePagerView({ pagesAmount: 4 });
// Animated style for page indicator
const indicatorStyle = useAnimatedStyle(() => {
const translateX = interpolate(
progress.position + progress.offset,
[0, pages.length - 1],
[0, (pages.length - 1) * 30],
Extrapolate.CLAMP
);
return {
transform: [{ translateX }],
};
});
return (
<View style={styles.container}>
{/* Page indicator */}
<View style={styles.indicatorContainer}>
{pages.map((_, index) => (
<View key={index} style={styles.dot} />
))}
<Animated.View style={[styles.activeDot, indicatorStyle]} />
</View>
<AnimatedPagerView
ref={ref}
style={styles.pagerView}
initialPage={0}
onPageScroll={onPageScroll}
onPageSelected={onPageSelected}
>
{pages.map((pageIndex) => (
<AnimatedPage key={pageIndex} pageIndex={pageIndex} progress={progress} />
))}
</AnimatedPagerView>
</View>
);
}
function AnimatedPage({ pageIndex, progress }: { pageIndex: number; progress: any }) {
const animatedStyle = useAnimatedStyle(() => {
const scale = interpolate(
Math.abs(progress.position - pageIndex) + progress.offset,
[0, 1],
[1, 0.8],
Extrapolate.CLAMP
);
const opacity = interpolate(
Math.abs(progress.position - pageIndex) + progress.offset,
[0, 1],
[1, 0.5],
Extrapolate.CLAMP
);
return {
transform: [{ scale }],
opacity,
};
});
return (
<Animated.View style={[styles.page, animatedStyle]}>
<Text style={styles.text}>Animated Page {pageIndex + 1}</Text>
</Animated.View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
indicatorContainer: {
flexDirection: 'row',
justifyContent: 'center',
paddingVertical: 20,
position: 'relative',
},
dot: {
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#ddd',
marginHorizontal: 5,
},
activeDot: {
position: 'absolute',
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#007AFF',
},
pagerView: { flex: 1 },
page: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f9f9f9',
margin: 20,
borderRadius: 10,
},
text: { fontSize: 24, fontWeight: 'bold' },
});Comprehensive state management features for dynamic page control and configuration.
/** State management methods */
interface StateManagement {
/** Current active page index */
activePage: number;
/** Array of page indices */
pages: number[];
/** Whether page transitions are animated */
isAnimated: boolean;
/** Whether scrolling is enabled */
scrollEnabled: boolean;
/** Whether overdrag is enabled */
overdragEnabled: boolean;
/** Current scroll state */
scrollState: 'idle' | 'dragging' | 'settling';
/** Current scroll progress */
progress: { position: number; offset: number };
}
/** State control methods */
interface StateControls {
/** Navigate to specific page (respects animation setting) */
setPage: (page: number) => void;
/** Add a new page to the end */
addPage: () => void;
/** Remove the last page (minimum 1 page) */
removePage: () => void;
/** Toggle scroll enabled state */
toggleScroll: () => void;
/** Toggle animation enabled state */
toggleAnimation: () => void;
/** Toggle overdrag enabled state */
toggleOverdrag: () => void;
}State Management Example:
import React from 'react';
import { View, Text, Button, Switch, StyleSheet } from 'react-native';
import { usePagerView } from 'react-native-pager-view';
export default function StateManagementExample() {
const {
ref,
activePage,
pages,
scrollState,
scrollEnabled,
isAnimated,
overdragEnabled,
progress,
setPage,
addPage,
removePage,
toggleScroll,
toggleAnimation,
toggleOverdrag,
onPageScrollStateChanged,
PagerView,
} = usePagerView({ pagesAmount: 3 });
return (
<View style={styles.container}>
<View style={styles.controls}>
<Text style={styles.info}>
Active: {activePage} | Pages: {pages.length} | State: {scrollState}
</Text>
<Text style={styles.info}>
Progress: {progress.position.toFixed(1)} + {progress.offset.toFixed(2)}
</Text>
<View style={styles.switchRow}>
<Text>Scroll Enabled:</Text>
<Switch value={scrollEnabled} onValueChange={toggleScroll} />
</View>
<View style={styles.switchRow}>
<Text>Animated:</Text>
<Switch value={isAnimated} onValueChange={toggleAnimation} />
</View>
<View style={styles.switchRow}>
<Text>Overdrag:</Text>
<Switch value={overdragEnabled} onValueChange={toggleOverdrag} />
</View>
<View style={styles.buttonRow}>
<Button title="Add Page" onPress={addPage} />
<Button title="Remove Page" onPress={removePage} />
</View>
<View style={styles.buttonRow}>
{pages.map((pageIndex) => (
<Button
key={pageIndex}
title={`Page ${pageIndex + 1}`}
onPress={() => setPage(pageIndex)}
/>
))}
</View>
</View>
<PagerView
ref={ref}
style={styles.pagerView}
initialPage={0}
scrollEnabled={scrollEnabled}
overdrag={overdragEnabled}
onPageScrollStateChanged={onPageScrollStateChanged}
>
{pages.map((pageIndex) => (
<View
style={[
styles.page,
{ backgroundColor: pageIndex % 2 === 0 ? '#e3f2fd' : '#f3e5f5' }
]}
key={pageIndex}
>
<Text style={styles.text}>Page {pageIndex + 1}</Text>
<Text style={styles.subtext}>
{isAnimated ? 'Animated Navigation' : 'Instant Navigation'}
</Text>
</View>
))}
</PagerView>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
controls: { padding: 16, backgroundColor: '#f5f5f5' },
info: { textAlign: 'center', marginBottom: 8, fontSize: 14 },
switchRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginVertical: 8,
},
buttonRow: {
flexDirection: 'row',
justifyContent: 'space-around',
marginVertical: 10,
},
pagerView: { flex: 1 },
page: {
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
text: { fontSize: 24, fontWeight: 'bold', marginBottom: 8 },
subtext: { fontSize: 16, color: '#666' },
});Install with Tessl CLI
npx tessl i tessl/npm-react-native-pager-view