Skip to content

Instantly share code, notes, and snippets.

@dannyhw
Last active May 31, 2024 10:43
Show Gist options
  • Save dannyhw/7b08e6e3bb7081d66a1e025c08edb8d5 to your computer and use it in GitHub Desktop.
Save dannyhw/7b08e6e3bb7081d66a1e025c08edb8d5 to your computer and use it in GitHub Desktop.
a simplified version of using useAnimatedRef and useScrollViewOffset for animating on scroll
import { Stack } from 'expo-router';
import { StyleSheet, Text, View, useWindowDimensions } from 'react-native';
import Animated, {
Extrapolation,
interpolate,
useAnimatedRef,
useAnimatedStyle,
useScrollViewOffset,
} from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function Home() {
const insets = useSafeAreaInsets();
const animatedRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(animatedRef);
const { fontScale } = useWindowDimensions();
const titleStyle = useAnimatedStyle(() => {
const offsetAmount = 100;
const opacity = interpolate(scrollOffset.value, [0, offsetAmount], [1, 0], Extrapolation.CLAMP);
const totalHeight = fontScale * 24 + 24;
const height = interpolate(
scrollOffset.value,
[0, offsetAmount],
[totalHeight, 0],
Extrapolation.CLAMP
);
return {
opacity,
justifyContent: 'center',
alignItems: 'flex-start',
height,
};
}, [fontScale, scrollOffset.value]);
return (
<View>
<Stack.Screen options={{ headerShown: false }} />
<View style={[{ paddingTop: insets.top }, styles.header]}>
<Animated.Text style={[titleStyle, styles.title]}>Home</Animated.Text>
<StatsBar />
</View>
<Animated.ScrollView
ref={animatedRef}
style={{ marginTop: 8 }}
contentContainerStyle={[styles.list, { paddingBottom: insets.bottom + 16 }]}>
<CardList />
</Animated.ScrollView>
</View>
);
}
const styles = StyleSheet.create({
header: {
paddingHorizontal: 16,
paddingBottom: 8,
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 3,
},
shadowOpacity: 0.27,
shadowRadius: 4.65,
elevation: 6,
},
list: {
paddingHorizontal: 16,
paddingTop: 16,
},
title: { fontSize: 24, fontWeight: 'bold', alignItems: 'center' },
});
const StatsBar = () => {
return (
<View style={{ justifyContent: 'space-between', flexDirection: 'row' }}>
<Chip>
<Text style={{ color: 'white' }}>credit:1$</Text>
</Chip>
<Chip>
<Text>points:2</Text>
</Chip>
<Chip>
<Text>abc:1</Text>
</Chip>
</View>
);
};
const CardList = () => {
return (
<>
<Card>
<Text>Hello</Text>
</Card>
<Card>
<Text>Hello</Text>
</Card>
<Card>
<Text>Hello</Text>
</Card>
<Card>
<Text>Hello</Text>
</Card>
<Card>
<Text>Hello</Text>
</Card>
<Card>
<Text>Hello</Text>
</Card>
</>
);
};
const Card = ({ children }: { children: React.ReactNode }) => {
return (
<View
style={{
padding: 16,
backgroundColor: 'white',
borderRadius: 8,
marginBottom: 16,
height: 300,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.23,
shadowRadius: 2.62,
elevation: 4,
}}>
{children}
</View>
);
};
const Chip = ({ children }: { children: React.ReactNode }) => {
return (
<View
style={{
paddingHorizontal: 8,
paddingVertical: 4,
backgroundColor: 'violet',
borderRadius: 8,
}}>
<Text style={{ color: 'white' }}>{children}</Text>
</View>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment