Hao Wu
Hao Wu

Reputation: 20669

createBottomTabNavigator with dynamic tabStyle for different tabs

According to the Document, I can change activeTintColor and activeBackgroundColor in tabBarOptions.

Is there a way to style the tab button with something like activeTabBarStyle?

I want to add a borderTop to the active tab, like this:

figma

So I created a function for the defaultNavigationOptions to dynamically assign the tabStyle for different tabs:

// ...
const BottomNavigator = createBottomTabNavigator({
    Users: {
        screen: UsersStackNavigator,
    },
    Dashboard: {
        screen: DashboardStackNavigator,
    },
    Coupons: {
        screen: CouponsStackNavigator,
    }
}, {
    defaultNavigationOptions: ({ navigation }) => {
        // ...
        const active = navigation.isFocused();
        const width = active ? 2 : 0;  // This outputs 3 times, which are 2, 0, 0
        return {
            // ...
            tabBarOptions: {
                // ...
                tabStyle: {
                    paddingTop: 10,
                    borderTopColor: '#3A3AB5',
                    borderTopWidth: width
                }
            }
        };
    }
});

The width seems working but all the three tabs are only using the activated navigationOptions:

I don't know why the color can be different why not other styles as well?

enter image description here

Any ideas how to work around with it?

Upvotes: 2

Views: 2303

Answers (1)

Auticcat
Auticcat

Reputation: 4489

I was able to achieve a specific tab styling behaviour in a demo project, here's the essential part of it,

First of all, i created a customBottomBar using react-navigation-tabs bottomTabBar, this is the component i used:

import React from 'react'
import { BottomTabBar } from 'react-navigation-tabs'
import { View, TouchableWithoutFeedback, Dimensions } from 'react-native'
import { StyleSheet } from 'react-native';
var { height } = Dimensions.get("window")

const TouchableWithoutFeedbackWrapper = ({
    onPress,
    onLongPress,
    testID,
    accessibilityLabel,
    ...props
}) => {
    if (props.focused) props.style.push(styles.tabBarStyle)
    return (
        <TouchableWithoutFeedback
            onPress={onPress}
            onLongPress={onLongPress}
            testID={testID}
            hitSlop={{
                left: 15,
                right: 15,
                top: 5,
                bottom: 5,
            }}
            accessibilityLabel={accessibilityLabel}
        >
            <View {...props} />
        </TouchableWithoutFeedback>
    )
}

export default TabBarComponent = props => {
    return <BottomTabBar
        {...props}
        style={styles.bottomBarStyle}
        getButtonComponent={() => {
            return TouchableWithoutFeedbackWrapper
        }}
    />
}

const styles = StyleSheet.create({
    bottomBarStyle: {
        //if you need to style the whole bottom bar
    },
    tabBarStyle: {
        borderTopWidth: 1
    }
})

What i did here is that i exported as-is the BottomTabBar provided by react-navigation, so it kept the same style i defined on the createBottomTabNavigator level.

After that, i used the getButtonComponent props, that lets me return a custom component for every button. For every button, react-navigation already passes the informations we need to render the button with the specific infos.

One of those informations is focused that let's me know which tab is getting rendered in a specific time.

Another info we get is the default style table react-navigation uses to renders his button which is an array, that's why i'm pushing it inside props.style

In the example I'm creating the button with the borderWidth: 1 style, but you can style it further based off your needs, i've left also a style you can use to style the bottomTabBar.

Created the customBottomBar you just need to import it where you defined you createBottomTabNavigator and pass it using tabBarComponent.

import BottomBar from "path/to/BottomBar"

createBottomTabNavigator({
   myScreen:{
      screen:myScreen
   }
   },{
   initialRouteName:"routeName",
   tabBarComponent: (props) => <BottomBar {...props} />
})

Let me know if i missed something or need explanation of something specific

Upvotes: 3

Related Questions