redesign completed
alot of work ahead
This commit is contained in:
1 parent
73d2c4c1ed
commit
febcdc111e
18 files changed
+1591
-845
No files matched your search
@@ -0,0 +1,131 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, View, Animated, Dimensions, ImageSourcePropType } from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { theme } from '../styles/theme';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
const HEADER_HEIGHT = 300;
|
||||
|
||||
interface ParallaxScrollViewProps {
|
||||
children: React.ReactNode;
|
||||
headerImage?: ImageSourcePropType;
|
||||
headerBackgroundColor?: string;
|
||||
headerContent?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ParallaxScrollView({
|
||||
children,
|
||||
headerImage,
|
||||
headerBackgroundColor = theme.colors.primary,
|
||||
headerContent,
|
||||
}: ParallaxScrollViewProps) {
|
||||
const scrollY = React.useRef(new Animated.Value(0)).current;
|
||||
|
||||
const headerTranslateY = scrollY.interpolate({
|
||||
inputRange: [0, HEADER_HEIGHT],
|
||||
outputRange: [0, -HEADER_HEIGHT / 2],
|
||||
extrapolate: 'clamp',
|
||||
});
|
||||
|
||||
const imageScale = scrollY.interpolate({
|
||||
inputRange: [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
|
||||
outputRange: [2, 1, 1],
|
||||
extrapolate: 'clamp',
|
||||
});
|
||||
|
||||
const headerOpacity = scrollY.interpolate({
|
||||
inputRange: [0, HEADER_HEIGHT / 2],
|
||||
outputRange: [1, 0],
|
||||
extrapolate: 'clamp',
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Animated.ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
onScroll={Animated.event(
|
||||
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
|
||||
{ useNativeDriver: true }
|
||||
)}
|
||||
scrollEventThrottle={16}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<View style={styles.contentContainer}>{children}</View>
|
||||
</Animated.ScrollView>
|
||||
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.header,
|
||||
{
|
||||
transform: [{ translateY: headerTranslateY }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Animated.View
|
||||
style={[
|
||||
StyleSheet.absoluteFill,
|
||||
{
|
||||
transform: [{ scale: imageScale }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={theme.gradients.primary}
|
||||
style={StyleSheet.absoluteFill}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
/>
|
||||
{headerImage && (
|
||||
<Animated.Image
|
||||
source={headerImage}
|
||||
style={[styles.headerImage, { opacity: 0.5 }]}
|
||||
/>
|
||||
)}
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View style={[styles.headerContent, { opacity: headerOpacity }]}>
|
||||
{headerContent}
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingTop: HEADER_HEIGHT,
|
||||
},
|
||||
contentContainer: {
|
||||
backgroundColor: theme.colors.background,
|
||||
borderTopLeftRadius: 32,
|
||||
borderTopRightRadius: 32,
|
||||
marginTop: -32,
|
||||
paddingTop: 32,
|
||||
minHeight: 800,
|
||||
},
|
||||
header: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: HEADER_HEIGHT,
|
||||
overflow: 'hidden',
|
||||
zIndex: 1,
|
||||
},
|
||||
headerImage: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
resizeMode: 'cover',
|
||||
},
|
||||
headerContent: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingBottom: 32,
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user