├── .babelrc ├── .gitignore ├── .watchmanconfig ├── App.js ├── README.md ├── app.json ├── assets ├── icon.png ├── me.jpg └── splash.png ├── babel.config.js ├── package.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo"], 3 | "env": { 4 | "development": { 5 | "plugins": [] 6 | }, 7 | "production": { 8 | "plugins": ["transform-remove-console"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p12 6 | *.key 7 | *.mobileprovision 8 | *.orig.* 9 | web-build/ 10 | web-report/ 11 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | ScrollView, 7 | Image, 8 | Animated 9 | } from 'react-native'; 10 | 11 | HEADER_MAX_HEIGHT = 120; 12 | HEADER_MIN_HEIGHT = 70; 13 | PROFILE_IMAGE_MAX_HEIGHT = 80; 14 | PROFILE_IMAGE_MIN_HEIGHT = 40; 15 | 16 | class App extends Component { 17 | constructor(props) { 18 | super(props); 19 | 20 | this.state = { 21 | scrollY: new Animated.Value(0) 22 | }; 23 | } 24 | render() { 25 | const headerHeight = this.state.scrollY.interpolate({ 26 | inputRange: [0, HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT], 27 | outputRange: [HEADER_MAX_HEIGHT, HEADER_MIN_HEIGHT], 28 | extrapolate: 'clamp' 29 | }); 30 | const profileImageHeight = this.state.scrollY.interpolate({ 31 | inputRange: [0, HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT], 32 | outputRange: [PROFILE_IMAGE_MAX_HEIGHT, PROFILE_IMAGE_MIN_HEIGHT], 33 | extrapolate: 'clamp' 34 | }); 35 | 36 | const profileImageMarginTop = this.state.scrollY.interpolate({ 37 | inputRange: [0, HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT], 38 | outputRange: [ 39 | HEADER_MAX_HEIGHT - PROFILE_IMAGE_MAX_HEIGHT / 2, 40 | HEADER_MAX_HEIGHT + 5 41 | ], 42 | extrapolate: 'clamp' 43 | }); 44 | const headerZindex = this.state.scrollY.interpolate({ 45 | inputRange: [0, HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT, 120], 46 | outputRange: [0, 0, 1000], 47 | extrapolate: 'clamp' 48 | }); 49 | 50 | const headerTitleBottom = this.state.scrollY.interpolate({ 51 | inputRange: [ 52 | 0, 53 | HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT, 54 | HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT + 5 + PROFILE_IMAGE_MIN_HEIGHT, 55 | HEADER_MAX_HEIGHT - 56 | HEADER_MIN_HEIGHT + 57 | 5 + 58 | PROFILE_IMAGE_MIN_HEIGHT + 59 | 26 60 | ], 61 | outputRange: [-20, -20, -20, 0], 62 | extrapolate: 'clamp' 63 | }); 64 | 65 | return ( 66 | 67 | 80 | 83 | 84 | Varun Nath 85 | 86 | 87 | 88 | 89 | 96 | 108 | 112 | 113 | 114 | 115 | Varun Nath 116 | 117 | 118 | 119 | 120 | 121 | 122 | ); 123 | } 124 | } 125 | export default App; 126 | 127 | const styles = StyleSheet.create({ 128 | container: { 129 | flex: 1, 130 | alignItems: 'center', 131 | justifyContent: 'center' 132 | } 133 | }); 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Twitter Header Scrolll Animation React Native(Expo) 2 | 3 | ![Alt Text](https://media.giphy.com/media/5qFgWw6g0NGefgchqX/giphy.gif) 4 | 5 | 6 | ## YouTube Tutorial Video 7 | * ### [Twitter Header Scroll Tutorial](https://www.youtube.com/watch?v=LP6zmnMcHR0&list=PLy9JCsy2u97npFZ8wylvgHcfB36qkmGmN) 8 | 9 | ## Installation Instructions 10 | 11 | ```js 12 | $ git clone https://github.com/nathvarun/Twitter-Header-Scroll-Animation-React-Native.git 13 | $ cd Twitter-Header-Scroll-Animation-React-Native.git 14 | $ npm install 15 | ``` 16 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "twitter-header-animated-youtube", 4 | "slug": "twitter-header-animated-youtube", 5 | "privacy": "public", 6 | "sdkVersion": "33.0.0", 7 | "platforms": ["ios", "android", "web"], 8 | "version": "1.0.0", 9 | "orientation": "portrait", 10 | "icon": "./assets/icon.png", 11 | "splash": { 12 | "image": "./assets/splash.png", 13 | "resizeMode": "contain", 14 | "backgroundColor": "#ffffff" 15 | }, 16 | "updates": { 17 | "fallbackToCacheTimeout": 0 18 | }, 19 | "assetBundlePatterns": ["**/*"], 20 | "ios": { 21 | "supportsTablet": true 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathvarun/Twitter-Header-Scroll-Animation-React-Native/26c4329d838f868e42b6d1a7ac9330860ded500a/assets/icon.png -------------------------------------------------------------------------------- /assets/me.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathvarun/Twitter-Header-Scroll-Animation-React-Native/26c4329d838f868e42b6d1a7ac9330860ded500a/assets/me.jpg -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathvarun/Twitter-Header-Scroll-Animation-React-Native/26c4329d838f868e42b6d1a7ac9330860ded500a/assets/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "babel-plugin-transform-react-jsx-source": "^6.22.0", 12 | "expo": "^33.0.0", 13 | "react": "16.8.3", 14 | "react-dom": "^16.8.6", 15 | "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz", 16 | "react-native-web": "^0.11.4" 17 | }, 18 | "devDependencies": { 19 | "babel-preset-expo": "^5.1.1" 20 | }, 21 | "private": true 22 | } 23 | --------------------------------------------------------------------------------