├── .gitignore
├── README.md
├── app.json
├── app
├── _layout.tsx
├── city.tsx
└── index.tsx
├── assets
└── images
│ ├── adaptive-icon.png
│ ├── favicon.png
│ ├── icon.png
│ ├── partial-react-logo.png
│ ├── react-logo.png
│ ├── react-logo@2x.png
│ ├── react-logo@3x.png
│ └── splash.png
├── babel.config.js
├── components
└── CityDetails.tsx
├── package.json
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | dist/
4 | npm-debug.*
5 | *.jks
6 | *.p8
7 | *.p12
8 | *.key
9 | *.mobileprovision
10 | *.orig.*
11 | web-build/
12 |
13 | # macOS
14 | .DS_Store
15 |
16 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
17 | # The following patterns were generated by expo-cli
18 |
19 | expo-env.d.ts
20 | # @end expo-cli
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to your Expo app 👋
2 |
3 | This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4 |
5 | ## Get started
6 |
7 | 1. Install dependencies
8 |
9 | ```bash
10 | npm install
11 | ```
12 |
13 | 2. Start the app
14 |
15 | ```bash
16 | npx expo start
17 | ```
18 |
19 | In the output, you'll find options to open the app in a
20 |
21 | - [development build](https://docs.expo.dev/develop/development-builds/introduction/)
22 | - [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
23 | - [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
24 | - [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
25 |
26 | You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
27 |
28 | ## Get a fresh project
29 |
30 | When you're ready, run:
31 |
32 | ```bash
33 | npm run reset-project
34 | ```
35 |
36 | This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
37 |
38 | ## Learn more
39 |
40 | To learn more about developing your project with Expo, look at the following resources:
41 |
42 | - [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
43 | - [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
44 |
45 | ## Join the community
46 |
47 | Join our community of developers creating universal apps.
48 |
49 | - [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
50 | - [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
51 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "expo-scroll-anim",
4 | "slug": "expo-scroll-anim",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/images/icon.png",
8 | "scheme": "myapp",
9 | "userInterfaceStyle": "automatic",
10 | "splash": {
11 | "image": "./assets/images/splash.png",
12 | "resizeMode": "contain",
13 | "backgroundColor": "#ffffff"
14 | },
15 | "ios": {
16 | "supportsTablet": true
17 | },
18 | "android": {
19 | "adaptiveIcon": {
20 | "foregroundImage": "./assets/images/adaptive-icon.png",
21 | "backgroundColor": "#ffffff"
22 | }
23 | },
24 | "web": {
25 | "bundler": "metro",
26 | "output": "static",
27 | "favicon": "./assets/images/favicon.png"
28 | },
29 | "plugins": [
30 | "expo-router"
31 | ],
32 | "experiments": {
33 | "typedRoutes": true
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/_layout.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | DarkTheme,
3 | DefaultTheme,
4 | ThemeProvider,
5 | } from "@react-navigation/native";
6 | import { useColorScheme } from "react-native";
7 | import { Stack } from "expo-router";
8 | import "react-native-reanimated";
9 |
10 | declare module "@react-navigation/native" {
11 | export type ExtendedTheme = {
12 | dark: boolean;
13 | colors: {
14 | primary: string;
15 | background: string;
16 | card: string;
17 | text: string;
18 | border: string;
19 | notification: string;
20 | subtitle: string;
21 | paragraph: string;
22 | overlay: string;
23 | };
24 | };
25 | export function useTheme(): ExtendedTheme;
26 | }
27 |
28 | const dark = {
29 | ...DarkTheme,
30 | colors: {
31 | ...DarkTheme.colors,
32 | subtitle: "#EEEEEE",
33 | paragraph: "#DDDDDD",
34 | overlay: "rgba(0,0,0,0.4)",
35 | },
36 | };
37 |
38 | const light = {
39 | ...DefaultTheme,
40 | colors: {
41 | ...DefaultTheme.colors,
42 | subtitle: "#333333",
43 | paragraph: "#222222",
44 | overlay: "rgba(255,255,255,0.1)",
45 | },
46 | };
47 |
48 | export default function RootLayout() {
49 | const colorScheme = useColorScheme();
50 | return (
51 |
52 |
60 |
61 |
67 |
68 |
69 | );
70 | }
71 |
--------------------------------------------------------------------------------
/app/city.tsx:
--------------------------------------------------------------------------------
1 | import { Dimensions, StyleSheet, Text, View } from "react-native";
2 | import React from "react";
3 | import { Image } from "expo-image";
4 | import { useTheme } from "@react-navigation/native";
5 | import Animated, {
6 | Extrapolation,
7 | interpolate,
8 | interpolateColor,
9 | useAnimatedRef,
10 | useAnimatedScrollHandler,
11 | useAnimatedStyle,
12 | useSharedValue,
13 | } from "react-native-reanimated";
14 | import { useSafeAreaInsets } from "react-native-safe-area-context";
15 | import { BlurView } from "expo-blur";
16 | import { useHeaderHeight } from "@react-navigation/elements";
17 | import CityDetails from "@/components/CityDetails";
18 |
19 | const IMAGE_URI =
20 | "https://wallpapers.com/images/hd/jal-mahal-water-palace-jaipur-nighttime-uhki0tnbfn2lgovf.jpg";
21 | const BANNER_HEIGHT = Dimensions.get("window").width;
22 | const IMAGE_HEIGHT = 50;
23 | const EXTRA_PADDING = 20;
24 |
25 | const City = () => {
26 | const theme = useTheme();
27 | const { top, bottom } = useSafeAreaInsets();
28 | const scrollRef = useAnimatedRef();
29 | const scrollOffset = useSharedValue(0);
30 |
31 | const HEADER_HEIGHT = useHeaderHeight();
32 |
33 | const UPPER_BOUND = [0, BANNER_HEIGHT / 2];
34 |
35 | const scrollHandler = useAnimatedScrollHandler({
36 | onScroll: (event) => {
37 | scrollOffset.value = event.contentOffset.y;
38 | },
39 | });
40 |
41 | const animatedHeaderStyle = useAnimatedStyle(() => {
42 | const height = interpolate(
43 | scrollOffset.value,
44 | [0, BANNER_HEIGHT / 2 + EXTRA_PADDING],
45 | [BANNER_HEIGHT, HEADER_HEIGHT + 10],
46 | Extrapolation.CLAMP
47 | );
48 | const translateY = interpolate(
49 | scrollOffset.value,
50 | [-BANNER_HEIGHT, 0, BANNER_HEIGHT],
51 | [-BANNER_HEIGHT * 0.5, 0, 0],
52 | Extrapolation.CLAMP
53 | );
54 |
55 | const scale = interpolate(
56 | scrollOffset.value,
57 | [-BANNER_HEIGHT, 0, BANNER_HEIGHT],
58 | [2, 1, 1],
59 | Extrapolation.CLAMP
60 | );
61 |
62 | return {
63 | height: height,
64 | transform: [{ translateY: translateY }, { scale: scale }],
65 | };
66 | });
67 |
68 | const animatedTitleStyle = useAnimatedStyle(() => {
69 | const scale = interpolate(
70 | scrollOffset.value,
71 | [-BANNER_HEIGHT / 2, 0, BANNER_HEIGHT / 2],
72 | [1.3, 1, 0.8],
73 | Extrapolation.CLAMP
74 | );
75 |
76 | const translateY = interpolate(
77 | scrollOffset.value,
78 | UPPER_BOUND,
79 | [
80 | BANNER_HEIGHT - 80,
81 | top + ((HEADER_HEIGHT - top) / 2 - IMAGE_HEIGHT / 1.8),
82 | ],
83 | Extrapolation.CLAMP
84 | );
85 |
86 | const translateX = interpolate(
87 | scrollOffset.value,
88 | [-BANNER_HEIGHT / 2, 0, BANNER_HEIGHT / 2],
89 | [scale * 2 * EXTRA_PADDING, EXTRA_PADDING, 2 * IMAGE_HEIGHT],
90 | Extrapolation.CLAMP
91 | );
92 |
93 | return {
94 | transform: [
95 | {
96 | translateX,
97 | },
98 | {
99 | translateY,
100 | },
101 | {
102 | scale,
103 | },
104 | ],
105 | };
106 | });
107 |
108 | const animatedImageStyle = useAnimatedStyle(() => {
109 | const width = interpolate(
110 | scrollOffset.value,
111 | UPPER_BOUND,
112 | [BANNER_HEIGHT, IMAGE_HEIGHT],
113 | Extrapolation.CLAMP
114 | );
115 |
116 | const translateY = interpolate(
117 | scrollOffset.value,
118 | UPPER_BOUND,
119 | [0, top + ((HEADER_HEIGHT - top) / 2 - IMAGE_HEIGHT / 1.8)],
120 | Extrapolation.CLAMP
121 | );
122 |
123 | const translateX = interpolate(
124 | scrollOffset.value,
125 | UPPER_BOUND,
126 | [0, IMAGE_HEIGHT],
127 | Extrapolation.CLAMP
128 | );
129 |
130 | const borderRadius = interpolate(
131 | scrollOffset.value,
132 | UPPER_BOUND,
133 | [0, width],
134 | Extrapolation.CLAMP
135 | );
136 |
137 | return {
138 | borderRadius: borderRadius,
139 | aspectRatio: 1,
140 | maxHeight: width,
141 | transform: [
142 | {
143 | translateY,
144 | },
145 | {
146 | translateX,
147 | },
148 | ],
149 | };
150 | });
151 |
152 | const animatedOverlay = useAnimatedStyle(() => {
153 | const backgroundColor = interpolateColor(scrollOffset.value, UPPER_BOUND, [
154 | theme.colors.overlay,
155 | "rgba(0,0,0,0)",
156 | ]);
157 | return {
158 | backgroundColor,
159 | };
160 | });
161 |
162 | const animatedPaddingSupport = useAnimatedStyle(() => {
163 | const height = interpolate(
164 | scrollOffset.value,
165 | [0, BANNER_HEIGHT - HEADER_HEIGHT - 100],
166 | [0, BANNER_HEIGHT - HEADER_HEIGHT - 100],
167 | Extrapolation.CLAMP
168 | );
169 | return {
170 | height: height,
171 | };
172 | });
173 |
174 | const ListTitle = () => {
175 | return (
176 |
177 |
178 | Jaipur
179 |
180 |
181 | The Pink Jewel of India
182 |
183 |
184 | );
185 | };
186 |
187 | const ListHeaderComponent = () => {
188 | return (
189 | <>
190 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | >
203 | );
204 | };
205 | return (
206 |
207 |
217 |
218 |
219 |
220 |
221 | );
222 | };
223 |
224 | export default City;
225 |
226 | const styles = StyleSheet.create({
227 | flexOne: {
228 | flex: 1,
229 | },
230 | contentContainerStyle: {
231 | gap: 25,
232 | },
233 | listTitleContainer: {
234 | position: "absolute",
235 | gap: 2,
236 | },
237 | titleStyle: {
238 | fontSize: 25,
239 | fontWeight: "500",
240 | },
241 | subTitleStyle: {
242 | fontSize: 15,
243 | fontWeight: "400",
244 | },
245 | headerStyle: {
246 | height: BANNER_HEIGHT,
247 | width: "100%",
248 | },
249 | bannerStyle: {
250 | flex: 1,
251 | overflow: "hidden",
252 | },
253 | });
254 |
--------------------------------------------------------------------------------
/app/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Pressable, StyleSheet, Text, View } from "react-native";
3 | import { useTheme } from "@react-navigation/native";
4 | import { useRouter } from "expo-router";
5 |
6 | const Main = () => {
7 | const router = useRouter();
8 | const theme = useTheme();
9 | return (
10 |
11 | router.navigate("/city")}>
12 | Main
13 |
14 |
15 | );
16 | };
17 |
18 | export default Main;
19 |
20 | const styles = StyleSheet.create({
21 | container: {
22 | flex: 1,
23 | justifyContent: "center",
24 | alignItems: "center",
25 | },
26 | });
27 |
--------------------------------------------------------------------------------
/assets/images/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/adaptive-icon.png
--------------------------------------------------------------------------------
/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/favicon.png
--------------------------------------------------------------------------------
/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/icon.png
--------------------------------------------------------------------------------
/assets/images/partial-react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/partial-react-logo.png
--------------------------------------------------------------------------------
/assets/images/react-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/react-logo.png
--------------------------------------------------------------------------------
/assets/images/react-logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/react-logo@2x.png
--------------------------------------------------------------------------------
/assets/images/react-logo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/react-logo@3x.png
--------------------------------------------------------------------------------
/assets/images/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arunabhverma/expo-animated-scroll-header/3df6890243b3f31872bfc94966c2032eab28f3c1/assets/images/splash.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/components/CityDetails.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, Text, View } from "react-native";
3 | import { useTheme } from "@react-navigation/native";
4 |
5 | export default function CityDetails() {
6 | const theme = useTheme();
7 | return (
8 |
9 |
10 | Jaipur is famously known as the Pink City due to the uniform terracotta
11 | pink hue of its buildings, a color that symbolizes hospitality. This
12 | tradition dates back to 1876 when the city was painted pink to welcome
13 | the Prince of Wales, later King Edward VII. The old part of the city
14 | still retains this pink charm, especially around the Johari Bazaar and
15 | Bapu Bazaar areas.
16 |
17 |
18 |
19 | The striking Hawa Mahal (Palace of Winds) is one of Jaipur’s most famous
20 | landmarks. Built in 1799, it was designed for royal women to observe
21 | street festivals and processions without being seen. Its façade, with
22 | 953 small windows or 'jharokhas', is an architectural masterpiece.
23 |
24 |
25 |
26 | History of Jaipur
27 |
28 |
29 | Jaipur's origins can be traced back to the reign of Maharaja Sawai Jai
30 | Singh II, who moved the capital from Amber Fort to Jaipur to accommodate
31 | the growing population and ensure better defense. The city was
32 | meticulously planned by architect Vidyadhar Bhattacharya based on the
33 | principles of Vastu Shastra, making it one of India’s first planned
34 | cities.
35 |
36 |
37 |
38 | The foundation of Jaipur in the 18th century marked the beginning of a
39 | new era for the Rajputs, as the city grew to become a center of arts,
40 | science, and culture.
41 |
42 |
43 |
44 | Jaipur's Royal Heritage
45 |
46 |
47 | Jaipur’s royalty continues to be a significant part of the city's
48 | identity. The City Palace is a royal residence that stands as a
49 | testament to Jaipur’s regal legacy. Parts of it have been converted into
50 | a museum, showcasing artifacts from the city’s illustrious past,
51 | including weapons, garments, and manuscripts.
52 |
53 |
54 |
55 | Another jewel of the Pink City is the Amber Fort, a short drive from
56 | Jaipur. This stunning hilltop fort was the capital before Jaipur and
57 | boasts a blend of Hindu and Mughal architecture. The fort's Sheesh Mahal
58 | (Hall of Mirrors) is one of its most captivating features.
59 |
60 |
61 |
62 | Jaipur's Festivals and Culture
63 |
64 |
65 | Jaipur is also a cultural hub, hosting a variety of festivals throughout
66 | the year that reflect the city's rich heritage. The Jaipur Literature
67 | Festival, held annually, is the world's largest free literary festival,
68 | attracting renowned authors from across the globe.
69 |
70 |
71 |
72 | The Teej and Gangaur festivals are celebrated with great enthusiasm in
73 | Jaipur. Teej is a monsoon festival that celebrates the union of Goddess
74 | Parvati and Lord Shiva, while Gangaur is dedicated to Goddess Gauri and
75 | Lord Shiva. These festivals feature processions, traditional dance, and
76 | music, adding to the city's vibrant cultural fabric.
77 |
78 |
79 |
80 | Jaipur's Cuisine
81 |
82 |
83 | No trip to Jaipur is complete without indulging in its rich and
84 | flavorful cuisine. Rajasthani dishes like Dal Baati Churma, Gatte Ki
85 | Sabzi, and Laal Maas are must-tries. The city's sweet treats, such as
86 | Ghewar, are especially popular during the festive season.
87 |
88 |
89 |
90 | Visitors can enjoy traditional Rajasthani thalis at local restaurants or
91 | experience fine dining at heritage hotels that offer authentic
92 | Rajasthani flavors combined with modern presentations.
93 |
94 |
95 |
96 | Modern Jaipur
97 |
98 |
99 | In addition to its historic landmarks, Jaipur is rapidly modernizing,
100 | with new developments in infrastructure, shopping malls, and luxury
101 | hotels. Yet, the city strikes a balance between preserving its royal
102 | past and embracing the future.
103 |
104 |
105 |
106 | From its bustling markets filled with traditional handicrafts, textiles,
107 | and gemstones to its luxurious palaces and forts, Jaipur offers an
108 | unforgettable blend of history, culture, and modernity.
109 |
110 |
111 | );
112 | }
113 |
114 | const styles = StyleSheet.create({
115 | container: {
116 | marginHorizontal: 16,
117 | },
118 | subtitle: {
119 | fontSize: 20,
120 | fontWeight: "bold",
121 | marginTop: 16,
122 | marginBottom: 8,
123 | },
124 | paragraph: {
125 | fontSize: 16,
126 | lineHeight: 24,
127 | marginBottom: 16,
128 | },
129 | });
130 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "expo-scroll-anim",
3 | "main": "expo-router/entry",
4 | "version": "1.0.0",
5 | "scripts": {
6 | "start": "expo start",
7 | "reset-project": "node ./scripts/reset-project.js",
8 | "android": "expo start --android",
9 | "ios": "expo start --ios",
10 | "web": "expo start --web",
11 | "test": "jest --watchAll",
12 | "lint": "expo lint"
13 | },
14 | "jest": {
15 | "preset": "jest-expo"
16 | },
17 | "dependencies": {
18 | "@expo/vector-icons": "^14.0.2",
19 | "@react-navigation/elements": "^1.3.31",
20 | "@react-navigation/native": "^6.0.2",
21 | "expo": "~51.0.28",
22 | "expo-blur": "~13.0.2",
23 | "expo-constants": "~16.0.2",
24 | "expo-font": "~12.0.9",
25 | "expo-image": "~1.13.0",
26 | "expo-linking": "~6.3.1",
27 | "expo-router": "~3.5.23",
28 | "expo-splash-screen": "~0.27.5",
29 | "expo-status-bar": "~1.12.1",
30 | "expo-system-ui": "~3.0.7",
31 | "expo-web-browser": "~13.0.3",
32 | "react": "18.2.0",
33 | "react-dom": "18.2.0",
34 | "react-native": "0.74.5",
35 | "react-native-gesture-handler": "~2.16.1",
36 | "react-native-reanimated": "~3.10.1",
37 | "react-native-safe-area-context": "4.10.5",
38 | "react-native-screens": "3.31.1",
39 | "react-native-web": "~0.19.10"
40 | },
41 | "devDependencies": {
42 | "@babel/core": "^7.20.0",
43 | "@types/jest": "^29.5.12",
44 | "@types/react": "~18.2.45",
45 | "@types/react-test-renderer": "^18.0.7",
46 | "jest": "^29.2.1",
47 | "jest-expo": "~51.0.3",
48 | "react-test-renderer": "18.2.0",
49 | "typescript": "~5.3.3"
50 | },
51 | "private": true
52 | }
53 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "expo/tsconfig.base",
3 | "compilerOptions": {
4 | "strict": true,
5 | "paths": {
6 | "@/*": [
7 | "./*"
8 | ]
9 | }
10 | },
11 | "include": [
12 | "**/*.ts",
13 | "**/*.tsx",
14 | ".expo/types/**/*.ts",
15 | "expo-env.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------