├── 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 |
--------------------------------------------------------------------------------