How to add icons to MaterialTopTabNavigator - react-native

I have an app in React Native v3. I have MaterialTopTabNavigator with text. It's working fine. But I need to add icons above text of tabs.
https://pasteboard.co/IuTpjGz.png
I have tried this (CommonIcon is my element, but I have also tried Icon from react-native-elements), but it's not working and VScode says ''CommonIcon' refers to a value, but is being used as a type here.'
When I run it in emulator, I got SyntaxError.
HomeScreen:{
screen:HomeScreen,
navigationOptions: {
tabBarLabel:"Home",
tabBarIcon: ({ tintColor }) => (
<CommonIcon name="ios-bookmarks" size={20}/>
)
},
},
...
tabBarOptions: {
showIcon: true
},
So my question is, how to createMaterialTopTabNavigator in React Native 3 with both labels and icons?

My colleague figured it out.
You should not put navigationOptions to the createMaterialTopTabNavigator. They belong to the page you want to go. In that page, you can specify options for it.
Main Page and Tab Navigator
export const IndraMainPage = createMaterialTopTabNavigator(
{
MarketTab: MarketPage,
TradesTab: TradesPage,
OrdersTab: OrdersPage,
EventsTab: EventsPage,
ReportsTab: ReportsPage,
},
{
order: ['ReportsTab', 'TradesTab', 'MarketTab', 'OrdersTab', 'EventsTab'],
initialRouteName: 'MarketTab',
tabBarPosition: 'bottom',
backBehavior: 'none',
lazy: true,
swipeEnabled: true,
tabBarOptions: {
upperCaseLabel: false,
activeTintColor: COLOR_PRIMARY,
inactiveTintColor: COLOR_TEXT,
showIcon: false,
tabStyle: {height: 55, flexDirection: 'column', padding: 0, paddingTop: 10},
style: {
backgroundColor: 'rgb(250,250,250)',
},
indicatorStyle: {backgroundColor: 'transparent'},
},
},
);
and then the specific page
export default class EventsPage extends Component<EventsPageProps, EventsPageState> {
static navigationOptions = {
tabBarVisible: true,
tabBarLabel: ({tintColor}: TabBarLabelProps) => (
<CenteredColumn>
<CommonIcon name="calendar" size={20} color={tintColor ? tintColor : COLOR_TEXT} />
<CommonText xs style={{color: tintColor ? tintColor : COLOR_TEXT}}>
Events Tab
</CommonText>
</CenteredColumn>
),
};
...

Related

Resetting screens to default react-native navigation

I am using this library with bottom tabs:
https://github.com/wix/react-native-navigation
for navigation, I have 3 tabs at the bottom, one of them is for home, the thing is I move from home screen to another screen it gets added to the stack, I want to be able to reset the stack whenever I click to the home icon again at bottom tabs.
The route.js is sth like this for the home icon at bottomTab:
stack: {
children: [
{
component: {
name: home,
}
},
],
options: {
bottomTab: {
iconInsets: {top: 6, left: 0, bottom: -6, right: 0},
titleDisplayMode: 'alwaysHide',
icon: require('../assets/images/home.png'),
selectedIconColor: colors.primary,
}
First you have to add listener if user click the bottom tab . With help of registerbottomtabselectedlistener you can achieve this . You can use popToRoot to send user to root of stack
// Subscribe
const bottomTabEventListener = Navigation.events().registerBottomTabSelectedListener(({ selectedTabIndex, unselectedTabIndex }) => {
Navigation.popTo(componentId); // check selectedTabIndex and send to home
});
...
// Unsubscribe
bottomTabEventListener.remove();
Not sure from the snippet you posted but I think you are trying to get bottom tabs to work. This is incomplete but hopefully this gets you on track.
const AppTabs = createBottomTabNavigator({
App: AppStack, // stack navigator
Contacts: ContactsStack, // stack navigator
Settings: {
screen: SettingsScreen, // single component import
navigationOptions: {
tabBarLabel: 'Settings',
tabBarIcon: ({ focused }) => (
<Ionicons
size={26}
name={Platform.OS === 'ios' ? 'ios-settings' : 'settings'}
style={{ marginBottom: -3 }}
color={focused ? "red" : "gray"}
/>
),
}
},
}, {
initialRouteName: 'App',
tabBarPosition: 'bottom',
swipeEnabled: true,
tabBarOptions: {
activeTintColor: 'green',
inactiveTintColor: 'gray',
labelStyle: {
fontSize: 16,
},
tabStyle: { marginBottom: -10 }
}
});
export default createAppContainer(createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
App: AppTabs,
Auth: AuthStack,
}, {
initialRouteName: 'AuthLoading',
}));

How can I conditionally set tabs in createBottomTabNavigator?

I have a static data file (json) that stores information like facebook page link. If the facebook page link is empty, I do NOT want the Follow Us tab to show. The facebook page link is stored in businessDataJSON.facebook. Is there a way to only show the Follow Us Tab if businessDataJSON.facebook is not empty (empty string)? This is my App.js:
const ListStack = createStackNavigator(
{
ListCategories: ListCategoriesScreen,
ListCategoryItems: ListCategoryItemsScreen
},
{
initialRouteName: "ListCategories",
defaultNavigationOptions: {
headerStyle: {
backgroundColor: businessDataJSON.theme.navigationBarBackground
},
headerTintColor: businessDataJSON.theme.navigationBarTint,
headerTitleStyle: {
fontWeight: "bold"
}
}
}
);
const FollowUsStack = createStackNavigator(
{
FollowUs: FollowUsScreen
},
{
initialRouteName: "FollowUs",
defaultNavigationOptions: {
headerStyle: {
backgroundColor: businessDataJSON.theme.navigationBarBackground
},
headerTintColor: businessDataJSON.theme.navigationBarTint,
headerTitleStyle: {
fontWeight: "bold"
}
}
}
);
export default createAppContainer(
createBottomTabNavigator(
{
ListTab: {
screen: ListStack,
navigationOptions: {
title: businessDataJSON.theme.tabBarListTitle,
tabBarIcon: ({ tintColor }) => (
<Icon
name={businessDataJSON.theme.tabBarListIcon}
size={17}
color={tintColor}
/>
)
}
},
FollowUsStack: {
screen: FollowUsStack,
navigationOptions: {
title: "Follow Us",
tabBarIcon: ({ tintColor }) => (
<Icon name="users" size={17} color={tintColor} />
)
}
}
},
{
tabBarOptions: {
activeTintColor: businessDataJSON.theme.tabBarIconActive,
inactiveTintColor: businessDataJSON.theme.tabBarIconInactive,
style: {
elevation: 8,
...Platform.select({
ios: { paddingTop: 4, paddingBottom: 4 },
android: {
borderTopWidth: 0,
paddingTop: 6,
paddingBottom: 6
}
})
}
}
}
)
);
Yes but you would need to make the creation of the tabs dinamic wich leads to the navigation prop to be lost and make a nightmare to use it without redux. The simple approach that i can see is to use a root createSwitchNavigator with a loading screen/start screen and the tabs as the 2nd screen. in the loading screen you check if there is your facebook page, and navigate to them accordingly. this example is for auth, but it works in your case . trust me, the navigation props is a nightmare to manage.

How to Style React-Navigation tab navigator with a mobx variable

I think I've just been staring at this too long, and now my brain doesn't work. I have mobx stores, one of which houses a basic theme color value. I want to pass this into my react-navigation tab background color, but I can't figure out how to do it. We are using Typescript, and that might be part of what is confusing me, because every time I try to inject my store, I get a bunch of errors.
Anyway, if someone could help me figure out how to either inject my store properly, or to pass a prop to my createMaterialTopTabNavigator function, I would greatly appreciate it.
Here is my top tab navigator code:
export const SignedInWithGroup = createMaterialTopTabNavigator(
{
Home: {
screen: MeetingStack,
navigationOptions: {
tabBarLabel: 'Advocacy Day',
tabBarIcon: <Ionicons name="md-home" size={24} />,
},
},
Legislators: {
screen: Legislators,
navigationOptions: {
tabBarLabel: 'Legislators',
tabBarIcon: <Ionicons name="ios-people" size={24} />,
},
},
Messages: {
screen: Messages,
navigationOptions: {
tabBarLabel: 'Messages',
tabBarIcon: <Ionicons name="ios-chatboxes" size={24} />,
},
},
Directory: {
screen: DirectoryStack,
navigationOptions: {
tabBarLabel: 'Directory',
tabBarIcon: <MaterialIcons name="contacts" size={24} />,
},
},
More: {
screen: MoreStack,
navigationOptions: {
tabBarLabel: 'More',
tabBarIcon: <MaterialIcons name="more" size={24} />,
},
},
},
{
tabBarPosition: 'bottom',
tabBarOptions: {
showIcon: true,
style: {
paddingTop: Platform.OS === 'android' ? 0 : 0,
backgroundColor: "#CCBE00", //Replace with theme color
},
tabStyle: {
padding: 0,
},
labelStyle: {
marginTop: Platform.OS === 'ios' ? 8 : 0,
marginBottom: Platform.OS === 'ios' ? 20 : 10,
marginLeft: 15,
fontSize: 7,
color: 'white',
},
},
}
);
export const createRootNavigator = (props:any, signedIn = false) => {
console.log("Props");
console.log(props);
return createSwitchNavigator(
{ SignedInWithGroup: { screen: SignedInWithGroup }, SignedOut },
{ initialRouteName: signedIn ? 'SignedInWithGroup' : 'SignedOut' }
);
};
and here is what is in my app.js:
const Layout = createRootNavigator(signedIn);
return (
<Provider {...stores}>
<Layout />
</Provider>
);
Solution
Use your custom tabbar from MaterialTopTabBar.
Install the react-navigation-tabs module. Because, react-navigation's TabNaviagtion is from react-navigation-tabs. (srcs)
$ yarn install react-navigation-tabs
or
$ npm install react-navigation-tabs --save
Make your custom tabbar component observing store(MobX) for the tabBarComponent option . I do not write code related in MobX or Redux.
import React, { Component } from 'react';
import { MaterialTopTabBar } from 'react-navigation-tabs';
// create a component
class TabBar extends Component {
  render() {
    return (
      <MaterialTopTabBar
        {...this.props}
        style={{ backgroundColor: 'green' }} // Replace with theme color. You should use observing variable from MobX or Redux.
      />
    );
  }
}
//make this component available to the app
export default TabBar;
Apply your custom tabbar in createMaterialTopTabNavigator.
const TabNavigation = createMaterialTopTabNavigator(
  {
    Home: HomeScreen,
    Login: HomeScreen,
    Register: HomeScreen,
  },
  {
    tabBarComponent: (props) => { // Use your custom tabbar here.
return (
<TabBar
{...props}
/>
);
},
tabBarPosition: 'bottom',
tabBarOptions: {
showIcon: true,
style: {
paddingTop: Platform.OS === 'android' ? 0 : 0,
},
tabStyle: {
padding: 0,
},
labelStyle: {
marginTop: Platform.OS === 'ios' ? 8 : 0,
marginBottom: Platform.OS === 'ios' ? 20 : 10,
marginLeft: 15,
fontSize: 7,
color: 'white',
},
},
}
);
Why?
As I wrote, react-navigation-tabs is used as TabNavigation basically in react-navigation And you can use custom view through tabBarComponent option when you createTabNavigator
There are some mudules you can use.
Navigators
createBottomTabNavigator
createMaterialTopTabNavigator
Views
BottomTabBar
MaterialTopTabBar (You used this view)
Utils
createTabNavigator
Thus, extending component or making your custom tabbar from BottomTabBar or MaterialTopTabBar can be one of the easily solutions.

TabNavigator extra padding

How to style the TabNavigator Tab's height and padding? Im doing the following:
import Icon from "react-native-vector-icons/MaterialIcons";
const tabNav = TabNavigator({
TabItem1: {
screen: MainScreen,
navigationOptions: {
tabBarLabel:"Home",
tabBarIcon: ({ tintColor }) => <Icon name={"home"} size={20} color={tintColor} />
}
},
TabItem2: {
screen: MainScreen,
navigationOptions: {
tabBarLabel:"Home",
tabBarIcon: ({ tintColor }) => <Icon name={"home"} size={30} color={tintColor} />
}
},
TabItem3: {
screen: MainScreen,
navigationOptions: {
tabBarLabel:"Browse",
tabBarIcon: ({ tintColor }) => <Icon name={"home"} color={tintColor} />
}
}
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#222',
activeBackgroundColor :'yellow', //Doesn't work
showIcon: true,
tabStyle: {
padding: 0, margin:0, //Padding 0 here
},
iconStyle: {
width: 30,
height: 30,
padding:0 //Padding 0 here
},
}
});
How do I get rid of the padding between the icon and the label? I did padding:0 in iconStyle and also in tabStyle but no luck. I want no padding below the label too. How do I do that? Thanks.
Found the extra padding is caused by View:
How do i get rid of that?
Solved by setting:
tabBarOptions: {
labelStyle: {
margin: 0
},
}
Try just style under tabBarOptions
tabBarOptions: {
style: {
height: 45
}
}
Unfortunately plenty of layout settings are hardcoded in this lib (like padding: 12 for tab which comes by default from elsewhere).
The only option is to look in node_modules\react-navigation\lib\views\TabView\ files and adjust as needed to your requirements.
Right now I'm hacking those sourses to find a quick-n-dirty way to allow rectangular (x>y), not only square (x=y, as defaulted) tab icons.
Other option is to create your custom tabBar component as maintainers suggest
I just did it by looking at this page https://reactnavigation.org/docs/en/material-top-tab-navigator.html
my TabStack looks like this:
const tabBarOptions = {
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 100,
},
style: {
paddingTop: 50,
backgroundColor: 'red',
},
}
export const TabStack = createMaterialTopTabNavigator({
History: History,
Current: Current,
Settings: Settings,
}, {
tabBarOptions: tabBarOptions
});
If you are using SafeAreaView inside your screen, remove it from root and you will be fine
Ran into a similar problem today and came across this post. My issue however had a - paddingBottom: 30 - being applied to the tabBarStyle.
I did not want to overwrite the package files since it could either lead to unforeseen issues elsewhere or it will be overwritten in future updates.
I simply set the value to it's negative to bring the overall padding being applied to 0 - ie. paddingBottom: -30
Not sure if it'll help someone but it helped me.
This is the actual way how you style your tab navigator
const screenOptions = {
tabBarStyle:{
height:50,
},
tabBarItemStyle:{
margin:5,
}
};
<Tab.Navigator {...{ screenOptions }}>
//Tabs Here
</Tab.Navigator >

How to hide TabBar Text in TabNavigator?

I'm using TabNavigator from 'react-navigation'. I want to hide or remove Text under icons.
Here is a part of TabNavigator. (I'm using Expo)
Camera: {
screen: CameraScreen,
},
Noti: {
screen: NotificationScreen,
},
Menu: {
screen: MenuStackNavigator,
},
},
{
navigationOptions: ({ navigation }) => ({
header: null, <<<
tabBarIcon: ({ focused }) => {
...
},
}),
header: null, <<<-
headerMode: 'none', <<--
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
backBehavior: 'none',
And this is CamaraScreen
class CameraScreen extends Component {
static navigationOptions = {
title: 'Camera'
}
You can hide the label by specifying showLabel: false for the tabBarOptions object:
backBehavior: 'none',
tabBarOptions: {
showLabel: false
}
You can hide the label by specifying tabBarShowLabel: false for the screenOptions object:
headerShown: false,
tabBarStyle: { backgroundColor: "#000000", borderTopWidth: 0 },
tabBarShowLabel: false,
}}```