1. ホーム
  2. React Native
  3. React Navigationのタブナビゲーションをカスタマイズしてみよう!

React Navigationのタブナビゲーションをカスタマイズしてみよう!

目次

  1. はじめに
  2. まずはデフォルトのタブナビゲーションを実装
  3. タブナビゲーションをカスタマイズする
  4. まとめ

はじめに

前回、React Navigationを使って画面下部にタブナビゲーションを作りました。

React Navigationでタブナビゲーションを作ろう!

今回は、画面上部にタブナビゲーションを作り、さらにタブナビゲーションをカスタマイズする方法をご紹介します!

まずはデフォルトのタブナビゲーションを実装

まずはReact Navigationデフォルトのタブナビゲーションを実装してみましょう。

前回はReact Navigationの createBottomTabNavigator コンポーネントを使って、画面下部にナビゲーションを作りました。

今回は、React Navigationの createMaterialTopTabNavigator というコンポーネントを使用して、画面上部にナビゲーションを作ります。

App.js は以下のようなコードになります。


import React, { Component } from 'react';
import {
  Text,
  View
} from 'react-native';
import { createMaterialTopTabNavigator } from 'react-navigation';

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>HomeScreen</Text>
      </View>
    );
  }
}

class DetailScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>DetailScreen</Text>
      </View>
    );
  }
}

class SettingScreen extends React.Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>SettingScreen</Text>
      </View>
    );
  }
}

const RootStack = createMaterialTopTabNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Detail: {
      screen: DetailScreen,
    },
    Setting: {
      screen: SettingScreen,
    }
  },
  {
    initialRouteName: 'Home',
  }
);

export default class App extends React.Component {
  render() {
    return <RootStack />;
  }
}

前回の記事のコードとほとんど変わりませんね!

前回のコードから変わった点は

  • SettingScreen(HomeScreen, DetailScreenとほぼ同じ)を追加
  • createMaterialTopTabNavigator コンポーネントを使用

の2点のみです。
この App.js については前回の記事で解説していますので、ぜひ参考にしてみてください。

タブナビゲーションをカスタマイズする

それではタブナビゲーションをカスタマイズしていきましょう!

今回は、アプリ版Bagelee のような見た目のタブを作ってみました。

slidetab.gif (359.0 kB)

タブの下のメイン画面を左右にスワイプすると、上のタブナビゲーションも切り替わります。
もちろん、タブをタップするとその画面に遷移することができます。

実際のアプリ版Bageleeでは、 react-native-tab-view というライブラリを使用しており、もう少し複雑な実装になっています

それでは、コードを見ていきましょう!

先程の App.jsRootStack の定義の上に、AppTabNavigation というナビゲーションのカスタマイズ用のコンポーネントを作成しました。
(追加した前後のコードは先程と一緒なので省略します)


(省略)

class AppTabNavigation extends React.Component {
  render() {
    const { navigation } = this.props;
    const { routes, index } = this.props.navigation.state;
    const {
      containerStyle,
      tabStyle,
      selectedTabStyle,
      textStyle,
      selectedTextStyle,
    } = styles;
    return (
      <View style={containerStyle}>
        {routes.map((route, idx) => {
          if (index === idx) {
            return (
              <View key={idx} style={[tabStyle, selectedTabStyle]}>
                <Text style={[textStyle, selectedTextStyle]}>{naviTitles[idx]}</Text>
              </View>
            );
          }
          return (
            <TouchableOpacity
              style={tabStyle}
              key={idx}
              onPress={() => { navigation.navigate(route.routeName); }}
            >
              <Text style={textStyle}>{naviTitles[idx]}</Text>
            </TouchableOpacity>
          );
        })}
      </View>
    );
  }
}

const styles = {
  containerStyle: {
    paddingTop: 30,
    borderBottomWidth: 3,
    borderBottomColor: '#5ab4bd',
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-between',
    backgroundColor: '#fcf6d6',
  },
  tabStyle: {
    flex: 1,
    marginRight: 1,
    marginLeft: 1,
    height: 40,
    borderTopLeftRadius: 16,
    borderTopRightRadius: 16,
    backgroundColor: '#ffffff',
  },
  selectedTabStyle: {
    backgroundColor: '#5ab4bd', 
  },
  textStyle: {
    fontWeight: 'bold',
    textAlign: 'center',
    paddingTop: 14,
  },
  selectedTextStyle: {
    color: '#ffffff',
  },
}

const RootStack = createMaterialTopTabNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Detail: {
      screen: DetailScreen,
    },
    Setting: {
      screen: SettingScreen,
    }
  },
  {
    initialRouteName: 'Home',
    tabBarComponent: AppTabNavigation,
  }
);

export default class App extends React.Component {
(省略)

コードの解説

まずは AppTabNavigation コンポーネントの中身を見ていきましょう。

class AppTabNavigation extends React.Component {
  render() {
    const { navigation } = this.props;
    const { routes, index } = navigation.state;

React Navigationのスクリーンに設定されたコンポーネントには、自動的に navigation というpropsが渡されます。

  • const { navigation } = this.props;
    こちらがその自動的に渡された navigation です。

  • const { routes, index } = navigation.state
    こちらでは、 navigationstate の中身を取り出しています。

routesとindex

  • routes
    スクリーン一つ一つの「keyとparamsとrouteName」が配列になって入っています。
    keyとrouteNameには、 RootStackコンポーネントでそれぞれのスクリーンのkeyとして設定した文字列(今回だと「Home」「Detail」「Setting」)が入っています。
  • index
    画面に表示されているスクリーンの位置を現す数値が入っています。
    例えば、メイン画面を表示しているときは「0」、詳細画面を表示しているときは「1」、というような感じです。

ほかにもReact Navigationのpropsは種類があるので、React NavigationのDocsを確認してみてください!

次は return の中身です!

    return (
      <View style={containerStyle}>
        {routes.map((route, idx) => {
          if (index === idx) {
            return (
              <View key={idx} style={[tabStyle, selectedTabStyle]}>
                <Text style={[textStyle, selectedTextStyle]}>{naviTitles[idx]}</Text>
              </View>
            );
          }
          return (
            <TouchableOpacity
              style={tabStyle}
              key={idx}
              onPress={() => { navigation.navigate(route.routeName); }}
            >
              <Text style={textStyle}>{naviTitles[idx]}</Text>
            </TouchableOpacity>
          );
        })}
      </View>
    );

1行目の <View style={containerStyle}> で、タブナビゲーション全体を囲っています。

3行目の {routes.map((route, idx) => { 以下で、 routes の中身ひとつひとつに対して処理を実行し、タブ部分を作っています。

          if (index === idx) {
            return (
              <View key={idx} style={[tabStyle, selectedTabStyle]}>
                <Text style={[textStyle, selectedTextStyle]}>{naviTitles[idx]}</Text>
              </View>
            );
          }

index(現在表示しているスクリーンの位置)と、idx (配列のインデックス番号)が同じ場合は、現在表示しているタブ用にスタイルを当てたJSXを返します。

今回だと、背景色を付けたりテキストの文字色を白にしたりしています。

          return (
            <TouchableOpacity
              style={tabStyle}
              key={idx}
              onPress={() => { navigation.navigate(route.routeName); }}
            >
              <Text style={textStyle}>{naviTitles[idx]}</Text>
            </TouchableOpacity>
          );

index(現在表示しているスクリーンの位置)と、idx (配列のインデックス番号)が一致していない場合は、現在表示していないタブということになります。

そこで、 TouchableOpacity を使ったタブを作り、タブをタップした際にその画面に遷移できるようにします。

5行目の onPress={() => { navigation.navigate(route.routeName); }} に注目してください。
navigation.navigate()は、別の画面に遷移するためのメソッドです。
引数には、タップした際に遷移したいスクリーンのkeyを指定します。

今回の場合だと、 routes.routeName にkeyが入っているので、そちらを指定します。

最後は RootStack の部分です!

const RootStack = createMaterialTopTabNavigator(
  {
    Home: {
      screen: HomeScreen,
    },
    Detail: {
      screen: DetailScreen,
    },
    Setting: {
      screen: SettingScreen,
    }
  },
  {
    initialRouteName: 'Home',
    tabBarComponent: AppTabNavigation,
  }
);

このように、 tabBarComponent にタブナビゲーションのカスタマイズ用のコンポーネントを設定します。
今回だと、さっき作った AppTabNavigation を指定しました。

これでカスタマイズされたタブナビゲーションの完成です!

まとめ

今回はReact Navigationでタブナビゲーションをカスタマイズする方法をご紹介しました!

このようにカスタマイズできると、アプリに合ったタブナビゲーションを実装できるのでとても良いですね。
ぜひ今回ご紹介したコードを参考に、タブナビゲーションをカスタマイズしてみてください。

Author Profile

うえまつ ゆい
うえまつ ゆい
文系大学を卒業後、サーバーサイドエンジニアを経てフロントエンドエンジニアになりました。

今はReact Nativeでのアプリ開発をしています。

この記事は
参考になりましたか?

PAGE TOP