I have this Custom React Native Bottom Navigation Component built with :
- @react-navigation/bottom-tabs
- react-native-reanimated
Basically I want it to have scale animation whenever the tab goes in / out focus.
Video demonstration here : https://imgur.com/a/t1IqrbZ
as you can see currently it only animates when the tab is being focused, meanwhile the previous tab did not animate at all
import React, { useEffect, useState } from 'react';
import { BottomTabBarButtonProps, createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { useIntl } from 'react-intl';
import { Text, TouchableOpacity, View, ViewStyle } from 'react-native';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import Gap from 'components/Gap';
//File Import
import HomeScreen from 'screens/home/HomeScreen';
import CategoryHomeScreen from 'screens/category/CategoryHomeScreen';
import VolunteerHomeScreen from 'screens/volunteer/VolunteerHomeScreen';
import ProfileHomeScreen from 'screens/profile/ProfileHomeScreen';
//Utils Import
import { CATEGORY_HOME, HOME, PROFILE_HOME, VOLUNTEER_HOME } from 'utils/routesConstant';
import useTheme from 'utils/hooks/useTheme';
import { IcCategory, IcHome, IcProfile, IcVolunteer } from 'assets/icons';
import { RootStackParams } from 'utils/routes';
const Tab = createBottomTabNavigator();
interface CustomTabBar extends BottomTabBarButtonProps{
name: string;
title: string;
component: ({ route, navigation }: NativeStackScreenProps<RootStackParams, any>) => React.JSX.Element;
icon: (focused?: boolean) => React.JSX.Element;
}
const MainBottomNavigation = () => {
const {Colors,Fonts} = useTheme();
const intl = useIntl();
const tabBarStyle:ViewStyle = {
position: 'absolute',
bottom:24,
left:16,
right:16,
borderRadius:10,
alignItems:'center',
justifyContent:'center',
height: 64,
elevation:1,
shadowOffset: {
width: 0,
height: 0,
},
shadowOpacity: 0.1,
shadowRadius: 4,
shadowColor: Colors.dropShadow,
backgroundColor:Colors.white
}
const TabArray = [
{
id:1,
name:HOME,
title:intl.formatMessage({defaultMessage:"Home"}),
component:HomeScreen,
icon:(focused?:boolean) => (
<IcHome stroke={focused ? Colors.primary : Colors.textPrimary} width={24} height={24}/>
)
}, ....
]
const CustomTabBar = (props:CustomTabBar) => {
const scale = useSharedValue(1.0);
const focused = props.accessibilityState?.selected
const {onPress} = props
const targetScale = focused ? 1.2 : 1.0;
//This only animates when tab is focoused in, when I navigate out from the tab it instantly goes to original size without animating.
scale.value = withSpring(targetScale, {
damping: 10,
stiffness: 800,
});
const tabMenuStyleAnimated = useAnimatedStyle(() => {
return {
transform: [{ scale: scale.value }],
};
});
return (
<TouchableOpacity activeOpacity={0.7} style={[{top:10,flex:1,alignItems:'center'}]} onPress={onPress}>
<Animated.View style={tabMenuStyleAnimated}>
{props.icon(focused)}
</Animated.View>
<Gap height={4} />
<Text style={[Fonts.fontMedium, Fonts.sizeXS, focused ? Fonts.textMainColor : Fonts.textPrimary,Fonts.textCenter]}>{props.title}</Text>
</TouchableOpacity>
)
}
return (
<Tab.Navigator
initialRouteName={HOME}
screenOptions={{
headerShown: false ,
tabBarShowLabel:false,
tabBarStyle
}}>
{TabArray.map((item,_)=>(
<Tab.Screen
key={item.id}
name={item.title as any}
component={item.component}
options={{
tabBarButton:(props)=><CustomTabBar {...props} title={item.title} component={item.component} icon={item.icon} name={item.name}/>
}}
/>
))}
</Tab.Navigator>
);
}
export default MainBottomNavigation;
Any idea of what I'm missing ?