| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- import type { PropsWithChildren, ReactElement } from 'react';
- import { StyleSheet } from 'react-native';
- import Animated, {
- interpolate,
- useAnimatedRef,
- useAnimatedStyle,
- useScrollOffset,
- } from 'react-native-reanimated';
- import { ThemedView } from '@/components/themed-view';
- import { useColorScheme } from '@/hooks/use-color-scheme';
- import { useThemeColor } from '@/hooks/use-theme-color';
- const HEADER_HEIGHT = 250;
- type Props = PropsWithChildren<{
- headerImage: ReactElement;
- headerBackgroundColor: { dark: string; light: string };
- }>;
- export default function ParallaxScrollView({
- children,
- headerImage,
- headerBackgroundColor,
- }: Props) {
- const backgroundColor = useThemeColor({}, 'background');
- const colorScheme = useColorScheme() ?? 'light';
- const scrollRef = useAnimatedRef<Animated.ScrollView>();
- const scrollOffset = useScrollOffset(scrollRef);
- const headerAnimatedStyle = useAnimatedStyle(() => {
- return {
- transform: [
- {
- translateY: interpolate(
- scrollOffset.value,
- [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
- [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
- ),
- },
- {
- scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
- },
- ],
- };
- });
- return (
- <Animated.ScrollView
- ref={scrollRef}
- style={{ backgroundColor, flex: 1 }}
- scrollEventThrottle={16}>
- <Animated.View
- style={[
- styles.header,
- { backgroundColor: headerBackgroundColor[colorScheme] },
- headerAnimatedStyle,
- ]}>
- {headerImage}
- </Animated.View>
- <ThemedView style={styles.content}>{children}</ThemedView>
- </Animated.ScrollView>
- );
- }
- const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- header: {
- height: HEADER_HEIGHT,
- overflow: 'hidden',
- },
- content: {
- flex: 1,
- padding: 32,
- gap: 16,
- overflow: 'hidden',
- },
- });
|