I have a buttom tab navigator which has a add screen and with a tab icon component. I the tab icon component has three button. I want to navigate to a different screen when i click on the button, but it doesn't work.
type BottonSheetParams = {
Home: undefined;
Overview: undefined;
Add: NavigatorScreenParams<TransactionsPrams>;
Budget: undefined;
Card: undefined;
};
const AppNavigator = () => {
return (
<BottomSheet.Navigator
screenOptions={({ route }) => ({
headerShown: false,
tabBarShowLabel: false,
tabBarIcon: ({ color, focused }) => {
if (route.name === "Home") {
return (
<TabItems
IconName="Home"
routeName="Home"
color={color}
focused={focused}
/>
);
} else if (route.name === "Overview") {
return (
<TabItems
IconName="LineChart"
routeName="Overview"
color={color}
focused={focused}
/>
);
} else if (route.name === "Budget") {
return (
<TabItems
IconName="Calculator"
routeName="Budget"
color={color}
focused={focused}
/>
);
} else if (route.name === "Card") {
return (
<TabItems
IconName="CreditCard"
routeName="Card"
color={color}
focused={focused}
/>
);
}
},
tabBarStyle: styles.tabBarStyle,
tabBarActiveTintColor: theme.colors.white,
})}
>
<BottomSheet.Screen name="Home" component={Dashboard} />
<BottomSheet.Screen name="Overview" component={Overview} />
<BottomSheet.Screen
name="Add"
component={TransactionsStack}
options={{
tabBarLabel: "",
tabBarShowLabel: false,
tabBarButton: () => {
return <AddButton />;
},
tabBarStyle: { display: "none" },
}}
/>
<BottomSheet.Screen
name="Budget"
component={Budget}
options={{
tabBarItemStyle: {
zIndex: 1,
},
}}
/>
<BottomSheet.Screen
name="Card"
component={Card}
options={{
tabBarItemStyle: {
zIndex: 1,
},
}}
/>
</BottomSheet.Navigator>
);
};
Transaction stack
type TransactionsPrams = {
AddIncomeScreen: undefined;
AddExpense: undefined;
};
const Transactions = createNativeStackNavigator<TransactionsPrams>();
const TransactionsStack = () => (
<Transactions.Navigator
screenOptions={{
headerShown: false,
presentation: "fullScreenModal",
}}
>
<Transactions.Screen name="AddIncomeScreen" component={Add} />
<Transactions.Screen name="AddExpense" component={AddExpense} />
</Transactions.Navigator>
);
this is the add button component:
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
const AddButton = () => {
const plusButton = useSharedValue("0deg");
const buttonBackgroundColor = useSharedValue(theme.colors.primary);
const pressed = useRef(false);
const [isPessed, setIsPessed] = useState(false);
const handlePressed = () => {
if (!isPessed) {
plusButton.value = "45deg";
buttonBackgroundColor.value = withTiming(theme.colors.tabBarNotFocused, {
duration: 200,
});
} else {
plusButton.value = "0deg";
buttonBackgroundColor.value = withTiming(theme.colors.primary, {
duration: 200,
});
}
setIsPessed(!isPessed);
};
const plusIconStyle = useAnimatedStyle(() => {
return {
transform: [{ rotate: plusButton.value }],
backgroundColor: buttonBackgroundColor.value,
};
});
return (
<View>
<AnimatedPressable
onPress={handlePressed}
style={[styles.addStyle, plusIconStyle]}
>
<Plus
color={theme.colors.white}
size={28}
absoluteStrokeWidth={false}
/>
</AnimatedPressable>
{isPessed && <ButtonOverlay isOpened={pressed.current} />}
</View>
);
};
export default AddButton;
this is the button overlay component:
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
const transAddIncomeY = -150;
const transTo = 20;
const ButtonOverlay = ({ isOpened }: { isOpened: boolean }) => {
const navigation =
useNavigation<NativeStackNavigationProp<TransactionsPrams>>();
const { height, width } = useWindowDimensions();
const addIncome = useSharedValue(0);
const addExpense = useSharedValue(0);
const accountTransfer = useSharedValue(0);
const plannedPayment = useSharedValue(0);
const overlayOpacity = useSharedValue(0);
const overlayOpacityY = useSharedValue(0);
const handlePresentModalPress = () => {
navigation.navigate("AddIncomeScreen");
// console.log("add income");
};
const openOverlay = () => {
addIncome.value = withTiming(0, { duration: 400 });
addExpense.value = withTiming(0, { duration: 400 });
plannedPayment.value = withTiming(0, { duration: 400 });
overlayOpacity.value = withTiming(0, { duration: 100 });
overlayOpacityY.value = withTiming(0, { duration: 50 });
};
const closeOverlay = () => {
addIncome.value = withSpring(transAddIncomeY, { duration: 300 });
addExpense.value = withSpring(transAddIncomeY, { duration: 300 });
accountTransfer.value = withSpring(transAddIncomeY, { duration: 400 });
plannedPayment.value = withTiming(1, { duration: 400 });
overlayOpacity.value = withTiming(1, { duration: 80 });
overlayOpacityY.value = withTiming(-1, { duration: 600 });
};
if (isOpened) {
openOverlay();
} else {
closeOverlay();
}
const addIncomeStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(
addExpense.value,
[transAddIncomeY, transTo],
[transAddIncomeY, 0]
),
},
{
translateX: interpolate(
addExpense.value,
[transAddIncomeY, 0],
[-130, 0]
),
},
{ scale: interpolate(addIncome.value, [transAddIncomeY, 0], [1, 0]) },
],
zIndex: 3,
};
});
const addExpenseStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(
addIncome.value,
[transAddIncomeY, transTo],
[-230, 0]
),
},
{ scale: interpolate(addExpense.value, [transAddIncomeY, 0], [1, 0]) },
],
zIndex: 3,
};
});
const accountTransferStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(
addExpense.value,
[transAddIncomeY, transTo],
[transAddIncomeY, 0]
),
},
{
translateX: interpolate(
addExpense.value,
[transAddIncomeY, 0],
[130, 0]
),
},
{ scale: interpolate(addIncome.value, [transAddIncomeY, 0], [1, 0]) },
],
zIndex: 3,
};
});
const plannedPaymentStyle = useAnimatedStyle(() => {
return {
opacity: plannedPayment.value,
zIndex: 3,
};
});
const overlayStyles = useAnimatedStyle(() => {
return {
width,
height,
top: -(height / 1.12),
left: -(width / 2.375),
opacity: interpolate(overlayOpacity.value, [1, 0], [1, 0]),
transform: [
{ translateY: interpolate(overlayOpacityY.value, [-150, 0], [150, 0]) },
],
pointerEvents: "none",
};
});
return (
<>
<Animated.View style={[styles.overlay, overlayStyles]} />
<View>
<AnimatedTransactionButton
buttonName="ADD INCOME"
icon="ArrowDown"
style={addIncomeStyle}
bgc={theme.colors.linearGreen}
onPress={handlePresentModalPress}
/>
<AnimatedTransactionButton
buttonName="ADD EXPENSE"
icon="ArrowUp"
style={addExpenseStyle}
bgc={theme.colors.linearRed}
onPress={() => console.log("Add expense")}
/>
<AnimatedTransactionButton
buttonName="ACCOUNT TRANSFER"
icon="Shuffle"
style={accountTransferStyle}
bgc={theme.colors.primary}
onPress={() => console.log("Account transfer")}
/>
<AnimatedPressable
style={[styles.plannedPaymentContainer, plannedPaymentStyle]}
onPress={() => console.log("planned payment")}
>
<Zap
color={theme.colors.white}
size={28}
absoluteStrokeWidth={false}
/>
<Text style={styles.plannedText}>Add planned payment</Text>
</AnimatedPressable>
</View>
</>
);
};
export default ButtonOverlay;
AnimatedTransactionButton:
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
type AnimatedTransactionButtonProp = {
icon: any;
style: StyleProps;
buttonName: string;
bgc: string;
onPress: () => void;
};
const AnimatedTransactionButton = ({
buttonName,
icon,
style,
bgc,
onPress,
}: AnimatedTransactionButtonProp) => {
return (
<Animated.View style={[styles.buttonContainer, style]}>
<AnimatedPressable
onPress={onPress}
style={[styles.defaultButtonStyle, { backgroundColor: bgc }]}
>
<Icon color={theme.colors.white} size={28} name={icon} />
</AnimatedPressable>
<Text style={styles.animatedText}>{buttonName}</Text>
</Animated.View>
);
};
export default AnimatedTransactionButton;
I tried this:
navigation.navigate("Transactions", { screen: "AddIncome" });
and i got this error: ERROR The action 'NAVIGATE' with payload {"name":"AddIncome"} was not handled by any navigator.
Do you have a screen named 'AddIncome'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
i tried this also and it didn't work:
navigation.navigate("AddIncome");