LifeSports Application(ReactNative & Nest.js) - 4. BottomNavigation

41413 ワード

#1 BottomNavigation


BottomNavigationは、ユーザーがボタンをクリックしたときにボタンを下に置き、必要な画面にジャンプできるナビゲーション機能です.

上のフラッシュメモリ画像はデータムナビゲーションです.

#2 BottomNavigation実施


私はBottomNavigationをホームページに置くので、HomeScreenではなくLoginscreenとRegisterScreenがいるStackNavigationにBottomNavigationを置きます.
以下のコマンドを使用してパッケージをインストールします.アイコンパッケージもインストールします.
npm install --save @react-navigation/bottom-tabs
npm install --save react-native-vector-icons/Ionicons
そしてBottomNavigatorディレクトリにBottomNavigationがナビゲーションを実現するためにjsを作成します.
  • /navigator/BottomNavigation
  • import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    import Icon from 'react-native-vector-icons/Ionicons';
    import palette from '../styles/palette';
    import HomeScreen from '../pages/home/HomeScreen';
    import PostScreen from '../pages/post/PostScreen';
    import MapScreen from '../pages/map/MapScreen';
    import MyPageScreen from '../pages/user/MyPageScreen';
    
    const Tab = createBottomTabNavigator();
    
    const BottomNavigation = ({ route }) => {
        return(
            <Tab.Navigator
                screenOptions={({ route }) => ({
                    tabBarIcon: ({ focused, color }) => {
                        var iconName;
                        var iconSize;
    
                        if(route.name === "Home") {
                            iconName = focused ? 'ios-home' : 'ios-home-outline';
                            iconSize = focused ? 32 : 24;
                        } else if (route.name === 'Board') {
                            iconName = focused ? 'ios-reader' : 'ios-reader-outline';
                            iconSize = focused ? 32 : 24;
                        } else if (route.name === 'Map'){
                            iconName = focused ? 'ios-location' : 'ios-location-outline';
                            iconSize = focused ? 32 : 24;
                        } else if (route.name === 'Setting'){
                            iconName = focused ? 'ios-person' : 'ios-person-outline';
                            iconSize = focused ? 32 : 24;
                        }
    
                        return (
                            <Icon 
                                size={ iconSize }
                                name={ iconName } 
                                color={ color }
                            />
                        )
                    }
                })}
    
                tabBarOptions = {{
                    activeTintColor: palette.blue[4],
                    inactiveTintColor: palette.gray[5],
                }}
            >
                <Tab.Screen 
                    name="Home"
                    children={
                        () => <HomeScreen />
                    }
                />
                <Tab.Screen 
                    name="Post"
                    children={
                        () => <PostScreen />
                    }
                />
                <Tab.Screen 
                    name="Map"
                    children={
                        () => <MapScreen />
                    }
                />
                <Tab.Screen 
                    name="MyPage"
                    children={
                        () => <MyPageScreen />
                    }
                />
            </Tab.Navigator>
        );
    };
    
    export default BottomNavigation;
  • /MainNavigation
  • import React from 'react';
    import 'react-native-gesture-handler';
    import { createStackNavigator } from '@react-navigation/stack';
    import { NavigationContainer } from '@react-navigation/native';
    import LoginScreen from '../pages/auth/LoginScreen';
    import RegisterScreen from '../pages/auth/RegisterScreen';
    import BottomNavigation from './BottomNavigation';
    
    const Stack = createStackNavigator();
    
    const StackNavigatior = () => {
        return(
            <NavigationContainer>
                <Stack.Navigator>
                
                    ...
                    
                    <Stack.Screen
                        name="Tab"
                        component={ BottomNavigation }
                        options={{
                            headerShown: false
                        }}
                    />
                </Stack.Navigator>
            </NavigationContainer>
        )
    }
    
    export default StackNavigatior;
  • LoginForm
  • import React from 'react';
    import { View, StyleSheet } from 'react-native';
    import StyledBorderButton from '../../../styles/common/StyledBorderButton';
    import StyledFullButton from '../../../styles/common/StyledFullButton';
    import StyledTextInput from '../../../styles/common/StyledTextInput';
    import palette from '../../../styles/palette';
    
    const LoginForm = ({ navigation }) => {
        ...
    
        const onPressMainNavigator = e => {
            e.preventDefault();
    
            navigation.navigate('Tab');
        };
    
        return(
            <View style={ styles.loginBox }>
                ...
                <StyledFullButton 
                    onPress={ onPressMainNavigator }
                    text="Sign in"
                />
                ...
            </View>
        );
    };
    
    ...
    
    export default LoginForm;
  • アイコンがEXPARKと表示されたら次のブログをご覧ください
    https://unchae.tistory.com/entry/RN-react-native-vector-icons-%EC%97%91%EB%B0%95%EC%9C%BC%EB%A1%9C-%EB%9C%B0-%EA%B2%BD%EC%9A%B0
  • コードを作成し、次のように「テスト」画面を表示します.



    アイコンとデータムナビゲーション機能は正常です.
    それではHomeScreenの画面を実現しましょうHomeScreenは、プロジェクトごとにカテゴリを作成する機能を提供しており、プロジェクトアイコンをクリックすると、それに関連する運動場所を地図に表示できます.
  • /home/components/HomeContent.js
  • import React from 'react';
    import { 
        StyleSheet,
        View
    } from 'react-native';
    import CategoryIcon from '../../../styles/common/CategoryIcon';
    import ImageIcon from '../../../styles/common/ImageIcon';
    import palette from '../../../styles/palette';
    
    const HomeContent = () => {
        return(
            <View style={ styles.container }>
                <View style={ styles.categoryLine }>
                    <CategoryIcon
                        name={ "ios-baseball-outline" }
                        text={ "야구" }
                        type_nm={ "야구장" }
                    />
                    <CategoryIcon
                        name={ "ios-basketball-outline" }
                        text={ "농구" }
                        type_nm={ "생활체육관" }
                    />
                    <CategoryIcon
                        name={ "ios-basketball" }
                        text={ "야외농구" }
                        type_nm={ "농구장" }
                    />
                    <CategoryIcon
                        name={ "ios-football-outline" }
                        text={ "축구" }
                        type_nm={ "축구장" }
                    />
                </View>
                <View style={ styles.categoryLine }>
                    <ImageIcon
                        name={ "arrow" }
                        text={ "양궁" }
                        type_nm={ "국궁장" }
                    />
                    <ImageIcon
                        name={ "badminton" }
                        text={ "배드민턴" }
                        type_nm={ "배드민턴장" }
                    />
                    <ImageIcon
                        name={ "climb" }
                        text={ "클라이밍" }
                        type_nm={ "클라이밍장" }
                    />
                    <ImageIcon
                        name={ "gateball" }
                        text={ "게이트볼" }
                        type_nm={ "게이트볼장" }
                    />
                </View>
                <View style={ styles.categoryLine }>
                    <ImageIcon
                        name={ "ice_skate" }
                        text={ "스케이트" }
                        type_nm={ "빙상장" }
                    />
                    <ImageIcon
                        name={ "inline_skate" }
                        text={ "인라인" }
                        type={ "인라인스케이트장" }
                    />
                    <ImageIcon
                        name={ "pingpong" }
                        text={ "탁구" }
                        type_nm={ "탁구장" }
                    />
                    <ImageIcon
                        name={ "sepak_takraw" }
                        text={ "족구" }
                        type_nm={ "족구장" }
                    />
                </View>
                <View style={ styles.categoryLine }>
                    <ImageIcon
                        name={ "shoot" }
                        text={ "사격" }
                        type_nm={ "사격장" }
                    />
                    <ImageIcon
                        name={ "swim" }
                        text={ "수영" }
                        type_nm={ "수영장" }
                    />
                    <ImageIcon
                        name={ "volleyball" }
                        text={ "배구" }
                        type_nm={ "구기체육관" }
                    />
                    <ImageIcon
                        name={ "volleyball" }
                        text={ "야외배구" }
                        type_nm={ "배구장" }
                    />
                </View>
                <View style={ styles.categoryLine }>
                    <CategoryIcon
                        name={ "ios-bicycle" }
                        text={ "자전거" }
                        type_nm={ "산악자전거장" }
                    />
                    <CategoryIcon
                        name={ "ios-school" }
                        text={ "학교체육" }
                        type_nm={ "학교체육시설" }
                    />
                    <CategoryIcon
                        name={ "ios-football" }
                        text={ "풋살" }
                        type_nm={ "풋살장" }
                    />
                    <ImageIcon
                        name={ "tennis" }
                        text={ "테니스" }
                        type_nm={ "테니스장" }
                    />
                </View>
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center',
            marginTop: 30,
            width: 420,
            backgroundColor: palette.white[0],
        },
        containerTitle: {
            alignItems: 'center',
            justifyContent: 'center',
        },
        textTitle: {
            fontWeight: 'bold',
            fontSize: 20,
        },
        categoryLine: {
            flexDirection: 'row',
            width: 420,
            height: 70,
            marginBottom: 20,
        },
    });
    
    export default HomeContent;
    カテゴリアイコンを含む構成部品.iKONを作ろう
  • /styles/common/CategoryIcon.js
  • import React from 'react';
    import { 
        StyleSheet, 
        View, 
        Text, 
        TouchableOpacity 
    } from 'react-native';
    import Icon from 'react-native-vector-icons/Ionicons';
    import palette from '../palette';
    
    const CategoryIcon = ({ 
        name, 
        text 
    }) => {
        return(
            <View style={ styles.container }>
                <TouchableOpacity>
                    <Icon 
                        size={ 48 }
                        name={ name }
                        color={ palette.blue[4] }
                    />
                </TouchableOpacity>
                <Text style={ styles.font }>
                    { text }
                </Text>
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            alignItems: 'center',
            justifyContent: 'center',
            width: 60,
            height: 60,
            margin: 20,
        },
        font: {
            fontWeight: 'bold',
        },
    });
    
    export default CategoryIcon;
  • /styles/common/ImageIcon.js
  • import React from 'react';
    import {
        StyleSheet,
        View,
        TouchableOpacity,
        Image,
        Text
    } from 'react-native';
    import palette from '../palette';
    import arrow from '../../assets/img/arrow.png';
    import badminton from '../../assets/img/badminton.png';
    import climb from '../../assets/img/climb.png';
    import gateball from '../../assets/img/gateball.png';
    import ice_skate from '../../assets/img/ice_skate.png';
    import inline_skate from '../../assets/img/inline_skate.png';
    import pingpong from '../../assets/img/pingpong.png';
    import sepak_takraw from '../../assets/img/sepak_takraw.png';
    import shoot from '../../assets/img/shoot.png';
    import swim from '../../assets/img/swim.png';
    import volleyball from '../../assets/img/volleyball.png';
    import tennis from '../../assets/img/tennis.png';
    
    const ImageIcon = ({ name, text }) => {
        if(name === "arrow") name = arrow
        else if(name === "badminton") name = badminton
        else if(name === "climb") name = climb 
        else if(name === "gateball") name = gateball 
        else if(name === "ice_skate") name = ice_skate
        else if(name === "inline_skate") name = inline_skate
        else if(name === "pingpong") name = pingpong
        else if(name === "sepak_takraw") name = sepak_takraw
        else if(name === "shoot") name = shoot
        else if(name === "swim") name = swim
        else if(name === "volleyball") name = volleyball
        else if(name === 'tennis') name = tennis;
    
        return(
            <View style={ styles.container }>
                <TouchableOpacity>
                    <Image
                        style={ styles.icon }
                        source={ name }
                    />
                </TouchableOpacity>
                <Text style={ styles.font }>
                    { text }
                </Text>
            </View>
        );
    };
    
    const styles = StyleSheet.create({
        container: {
            alignItems: 'center',
            justifyContent: 'center',
            width: 60,
            height: 60,
            margin: 20,
        },
        icon: {
            tintColor: palette.blue[4],
        }, 
        font: {
            fontWeight: 'bold',
        },
    });
    
    export default ImageIcon;
    ImageIconは、自分でダウンロードして作成したイメージファイルです.画像とフォントに関するファイルを襟に置きます.
    https://github.com/biuea3866/MyLifeSports
    次に、HomeScreenのタイトルセクションを変更します.
  • BottomNavigation.js
  • import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    import Icon from 'react-native-vector-icons/Ionicons';
    import palette from '../styles/palette';
    import HomeScreen from '../pages/home/HomeScreen';
    import PostScreen from '../pages/post/PostScreen';
    import MapScreen from '../pages/map/MapScreen';
    import MyPageScreen from '../pages/user/MyPageScreen';
    
    const Tab = createBottomTabNavigator();
    
    const BottomNavigation = ({ route }) => {
        return(
            ...
                <Tab.Screen 
                    name="Home"
                    options={{
                        title: 'Life Sport',
                        tabBarLabel: 'Home',
                        headerStyle: {
                            backgroundColor: palette.blue[4],
                        },
                        headerTintColor: palette.white[0],
                        headerTitleStyle: {
                            fontWeight: 'bold'
                        },
                    }}
                    children={
                        () => <HomeScreen />
                    }
                />
                ...
    };
    
    export default BottomNavigation;
    結果画面.

    よく撮れている様子が見られますこのようにして、投稿ページ、地図ページ、および私のページを作成します.