Add navigation element animations
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
101
src/components/hideableBottomNavigationBar.tsx
Normal file
101
src/components/hideableBottomNavigationBar.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { BottomNavigation } from 'react-native-paper';
|
||||
import { Animated, StyleSheet } from 'react-native';
|
||||
import {
|
||||
CommonActions,
|
||||
NavigationHelpers,
|
||||
ParamListBase,
|
||||
TabNavigationState,
|
||||
} from '@react-navigation/native';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
import { BottomTabNavigationEventMap } from '@react-navigation/bottom-tabs';
|
||||
import { BottomTabDescriptorMap } from '@react-navigation/bottom-tabs/lib/typescript/src/types';
|
||||
import { ROUTE } from '../types';
|
||||
|
||||
const hideableBottomNavigationBarStyles = StyleSheet.create({
|
||||
bar: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const HideableBottomNavigationBar = ({
|
||||
navigation,
|
||||
state,
|
||||
descriptors,
|
||||
insets,
|
||||
visible = true,
|
||||
routeCallback,
|
||||
}: {
|
||||
navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>;
|
||||
state: TabNavigationState<ParamListBase>;
|
||||
descriptors: BottomTabDescriptorMap;
|
||||
insets: EdgeInsets;
|
||||
visible?: boolean;
|
||||
routeCallback?: (route: ROUTE) => void;
|
||||
}) => {
|
||||
const visibleAnim = useRef(new Animated.Value(visible ? 0 : 1)).current;
|
||||
|
||||
useEffect(() => {
|
||||
Animated.timing(visibleAnim, {
|
||||
toValue: visible ? 0 : 1,
|
||||
duration: visible ? 200 : 150,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}, [visible, visibleAnim]);
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style={{
|
||||
marginBottom: insets.bottom,
|
||||
transform: [
|
||||
{
|
||||
translateY: visibleAnim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 80],
|
||||
}),
|
||||
},
|
||||
],
|
||||
...hideableBottomNavigationBarStyles.bar,
|
||||
}}>
|
||||
<BottomNavigation.Bar
|
||||
navigationState={state}
|
||||
safeAreaInsets={insets}
|
||||
onTabPress={({ route, preventDefault }) => {
|
||||
const event = navigation.emit({
|
||||
type: 'tabPress',
|
||||
target: route.key,
|
||||
canPreventDefault: true,
|
||||
});
|
||||
if (event.defaultPrevented) {
|
||||
preventDefault();
|
||||
} else {
|
||||
navigation.dispatch({
|
||||
...CommonActions.navigate(route.name, route.params),
|
||||
target: state.key,
|
||||
});
|
||||
if (routeCallback) routeCallback(route.name as ROUTE);
|
||||
}
|
||||
}}
|
||||
renderIcon={({ route, focused, color }) => {
|
||||
const { options } = descriptors[route.key];
|
||||
if (options.tabBarIcon) {
|
||||
return options.tabBarIcon({
|
||||
focused,
|
||||
color,
|
||||
size: 22,
|
||||
});
|
||||
}
|
||||
}}
|
||||
getLabelText={({ route }) => {
|
||||
const { options } = descriptors[route.key];
|
||||
return options.title ?? route.name;
|
||||
}}
|
||||
/>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
export default HideableBottomNavigationBar;
|
Reference in New Issue
Block a user