Search code examples
reactjsreact-nativenavigationscrollview

Add Horizontal ScrollView to Bottom Navigation Tab


I have to create an App for the final project of my class, and I decided to use React Native for that. But i'm just starting. I got this code from a youtube video, but looking at other snippets of code I'm wondering if this one is not a bit too complicated for what it is supposed to do.

I saw other ways of implementing a bottom navigation bar that would allow the add of horizontal scrollview between all the pages of my app

So I'm wondering, should i change my code completely or is there a way that i could add horizontal scrollview to it ?

Thanks in advance for your answers

FILE : MainContainer.js

import * as React from 'react';

import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons'

//Screens
import WelcomeScreen from './screens/Welcome'
import InventoryScreen from './screens/Inventory'
import PatientsScreen from './screens/Patients'

// Screen names
const welcomeName = 'Bienvenue'
const inventoryName = 'Inventaire'
const patientsName = 'Patients'

const Tab = createBottomTabNavigator();

export default function MainContainer(){
    return(
      <NavigationContainer>
        <Tab.Navigator 
        initialRouteName={welcomeName}
        screenOptions={({route}) => ({
            tabBarIcon: ({focused, color, size}) => {
                let iconName;
                let rn = route.name;

                if(rn === welcomeName){
                    iconName = focused ? 'home' : 'home-outline'
                } else if (rn === inventoryName){
                    iconName = focused ? 'list' : 'list-outline'
                } else if (rn === patientsName){
                    iconName = focused ? 'people-circle' : 'people-circle-outline'
                }

                return <Ionicons name={iconName} size={size} color={color}/>
            },
        })}
        tabBarOptions={{
            activeTintColor: 'tomato',
            inactiveTintColor: 'grey',
            labelStyle: { paddingBottom : 10, fontSize : 10},
            style: {padding: 10, height: 70},
        }}
        
        >

        <Tab.Screen name={welcomeName} component={WelcomeScreen}/>
        <Tab.Screen name={patientsName} component={PatientsScreen}/>
        <Tab.Screen name={inventoryName} component={InventoryScreen}/>

        </Tab.Navigator>
      </NavigationContainer>
    )
}

FILE : App.js

import * as React from 'react';
import MainContainer from './navigation/MainContainer';

function App(){
  return(
    <MainContainer></MainContainer>
  )
}

export default App;

Tried to create a HorizontalScrollView.js file but don't know if i can implement it in my MainContainer.js or App.js file

import React, { Component } from 'react';
import {
    AppRegistry,
    ScrollView,
    Text, View,
    Dimensions } from 'react-native';

export default class HorizontalScrollView extends Component {
    render(){
        let screenWidth = Dimensions.get('window').width;
        let screenHeight = Dimensions.get('window').height;
        return(
            <ScrollView
                horizontal={true}
            >
                // That's where i should add the views of each page
            </ScrollView>
        );
    }
}

Solution

  • To integrate horizontal scrolling, you need to wrap your individual screens with you HorizontalScrollView Component. But if you need to swipe between different screens, you have to use a different navigator like 'Material Top Tabs Navigator' (createMaterialTopTabNavigator): here you can position it to the bottom. This method is more acceptable since it is in line with how navigation between screens is generally handled in React Native.

    1. Install Package

    npm install @react-navigation/material-top-tabs react-native-tab-view
    npm install react-native-pager-view
    

    2. Modify MainContainer.js

    You can modify your MainContainer to support navigation functionality using createMaterialTopTabNavigator.

    import * as React from 'react';
    import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
    import { NavigationContainer } from '@react-navigation/native';
    import Ionicons from 'react-native-vector-icons/Ionicons';
    
    //Screens
    import WelcomeScreen from './screens/Welcome'
    import InventoryScreen from './screens/Inventory'
    import PatientsScreen from './screens/Patients'
    
    // Screen names
    const welcomeName = 'Bienvenue'
    const inventoryName = 'Inventaire'
    const patientsName = 'Patients'
    
    const Tab = createMaterialTopTabNavigator();
    
    export default function MainContainer(){
        return(
            <NavigationContainer>
            <Tab.Navigator 
                initialRouteName={welcomeName}
                tabBarPosition='bottom' // Position your tab bar to the bottom
                swipeEnabled={true} // Enable swipe functionality
                screenOptions={({route}) => ({
                    tabBarIcon: ({focused, color, size}) => {
                        let iconName;
                        let rn = route.name;
    
                        if(rn === welcomeName){
                            iconName = focused ? 'home' : 'home-outline'
                        } else if (rn === inventoryName){
                            iconName = focused ? 'list' : 'list-outline'
                        } else if (rn === patientsName){
                            iconName = focused ? 'people-circle' : 'people-circle-outline'
                        }
    
                        return <Ionicons name={iconName} size={size} color={color}/>
                    },
                })}
                tabBarOptions={{
                    activeTintColor: 'tomato',
                    inactiveTintColor: 'grey',
                    labelStyle: { paddingBottom : 10, fontSize : 10},
                    style: {padding: 10, height: 70},
                    showIcon: true, // Show icons
                    showLabel: false // If you want to hide labels and only show icons
                }}>
    
                <Tab.Screen name={welcomeName} component={WelcomeScreen}/>
                <Tab.Screen name={patientsName} component={PatientsScreen}/>
                <Tab.Screen name={inventoryName} component={InventoryScreen}/>
            </Tab.Navigator>
          </NavigationContainer>
        );
    }
    

    Here, the individual screens do not need to be wrapped with the 'HorizontalScrollView' component since 'createMaterialTopTabNavigator' handles swiping functionaity between screens. The 'swipeEnabled' prop make swiping between screens possible between screens and 'tabBarPosition='bottom' will position the tabs at bottom.

    Hope this will solve your problem.