├── App.js ├── README.md ├── app.json ├── assets ├── adaptive-icon.png ├── favicon.png ├── icon.png ├── plus.png └── splash.png ├── babel.config.js ├── package-lock.json └── package.json /App.js: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar'; 2 | import React from 'react'; 3 | import { Animated, Dimensions, Image, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; 4 | import 'react-native-gesture-handler'; 5 | import { NavigationContainer } from '@react-navigation/native'; 6 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; 7 | 8 | // Plus... 9 | import plus from './assets/plus.png' 10 | 11 | // Font Awesome Icons... 12 | import { FontAwesome5 } from '@expo/vector-icons' 13 | import { useRef } from 'react'; 14 | 15 | const Tab = createBottomTabNavigator(); 16 | 17 | // Hiding Tab Names... 18 | export default function App() { 19 | // Animated Tab Indicator... 20 | const tabOffsetValue = useRef(new Animated.Value(0)).current; 21 | return ( 22 | 23 | 44 | 45 | { 46 | // Tab Screens.... 47 | 48 | // Tab ICons.... 49 | } 50 | ( 52 | 57 | 62 | 63 | ) 64 | }} listeners={({ navigation, route }) => ({ 65 | // Onpress Update.... 66 | tabPress: e => { 67 | Animated.spring(tabOffsetValue, { 68 | toValue: 0, 69 | useNativeDriver: true 70 | }).start(); 71 | } 72 | })}> 73 | 74 | ( 76 | 81 | 86 | 87 | ) 88 | }} listeners={({ navigation, route }) => ({ 89 | // Onpress Update.... 90 | tabPress: e => { 91 | Animated.spring(tabOffsetValue, { 92 | toValue: getWidth(), 93 | useNativeDriver: true 94 | }).start(); 95 | } 96 | })}> 97 | 98 | 99 | { 100 | 101 | // Extra Tab Screen For Action Button.. 102 | } 103 | 104 | ( 106 | 107 | 108 | 117 | 122 | 123 | 124 | ) 125 | }}> 126 | 127 | ( 129 | 134 | 139 | 140 | ) 141 | }} listeners={({ navigation, route }) => ({ 142 | // Onpress Update.... 143 | tabPress: e => { 144 | Animated.spring(tabOffsetValue, { 145 | toValue: getWidth() * 3, 146 | useNativeDriver: true 147 | }).start(); 148 | } 149 | })}> 150 | 151 | ( 153 | 158 | 163 | 164 | ) 165 | }} listeners={({ navigation, route }) => ({ 166 | // Onpress Update.... 167 | tabPress: e => { 168 | Animated.spring(tabOffsetValue, { 169 | toValue: getWidth() * 4, 170 | useNativeDriver: true 171 | }).start(); 172 | } 173 | })}> 174 | 175 | 176 | 177 | 190 | 191 | 192 | 193 | ); 194 | } 195 | 196 | function getWidth() { 197 | let width = Dimensions.get("window").width 198 | 199 | // Horizontal Padding = 20... 200 | width = width - 80 201 | 202 | // Total five Tabs... 203 | return width / 5 204 | } 205 | 206 | function EmptyScreen() { 207 | return ( 208 | 209 | 210 | ); 211 | } 212 | 213 | function SettingsScreen() { 214 | return ( 215 | 216 | Settings! 217 | 218 | ); 219 | } 220 | 221 | function HomeScreen() { 222 | return ( 223 | 224 | Home! 225 | 226 | ); 227 | } 228 | 229 | function NotificationScreen() { 230 | return ( 231 | 232 | Notifications! 233 | 234 | ); 235 | } 236 | 237 | function SearchScreen() { 238 | return ( 239 | 240 | Search! 241 | 242 | ); 243 | } 244 | 245 | const styles = StyleSheet.create({ 246 | container: { 247 | flex: 1, 248 | backgroundColor: '#fff', 249 | alignItems: 'center', 250 | justifyContent: 'center', 251 | }, 252 | }); 253 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom Floating Bottom Tab Navigator In React Native 2 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "customtabbar", 4 | "slug": "customtabbar", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#FFFFFF" 26 | } 27 | }, 28 | "web": { 29 | "favicon": "./assets/favicon.png" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveKoding/customtabbar/27dba8f1be58a5e5a281e127f0e5f456d2a40b34/assets/adaptive-icon.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveKoding/customtabbar/27dba8f1be58a5e5a281e127f0e5f456d2a40b34/assets/favicon.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveKoding/customtabbar/27dba8f1be58a5e5a281e127f0e5f456d2a40b34/assets/icon.png -------------------------------------------------------------------------------- /assets/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveKoding/customtabbar/27dba8f1be58a5e5a281e127f0e5f456d2a40b34/assets/plus.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactiveKoding/customtabbar/27dba8f1be58a5e5a281e127f0e5f456d2a40b34/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 | "@react-native-community/masked-view": "0.1.10", 12 | "@react-navigation/bottom-tabs": "^5.11.11", 13 | "@react-navigation/native": "^5.9.4", 14 | "expo": "~41.0.1", 15 | "expo-status-bar": "~1.0.4", 16 | "react": "16.13.1", 17 | "react-dom": "16.13.1", 18 | "react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz", 19 | "react-native-gesture-handler": "~1.10.2", 20 | "react-native-reanimated": "~2.1.0", 21 | "react-native-safe-area-context": "3.2.0", 22 | "react-native-screens": "~3.0.0", 23 | "react-native-web": "~0.13.12" 24 | }, 25 | "devDependencies": { 26 | "@babel/core": "^7.9.0" 27 | }, 28 | "private": true 29 | } 30 | --------------------------------------------------------------------------------