2018年6月29日

プログラミング

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でタブナビゲーションをカスタマイズする方法をご紹介しました!

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

1

0

AUTHOR

うえまつゆい エンジニア

サーバーサイドエンジニアからフロントエンドエンジニアになりました。主にReact Nativeでのアプリ開発をしています。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

簡単に自分で作れるWebAR

「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。

palanARへ
palanar

palanはWebARの開発を
行っています

弊社では企画からサービスの公開終了まで一緒に関わらせていただきます。 企画からシステム開発、3DCG、デザインまで一貫して承ります。

webar_waterpark

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

しまだ

しまだ デザイナー

WebAR/VRのデザインと3DCG制作がメインです。 肩書きは「アニメ案件に関わりたいデザイナー」。

Miu マーケター

ドイツでWEBマーケティングしています。

しんのき エンジニア

主に React Native を使ったアプリ開発と AWS や Firebase を使ったサーバーレスアーキテクチャを担当しています。元々はインフラとかPHPをやっていました。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReact NativeやReact360をよく触っています。

furuya エンジニア

サーバーサイド、フロントエンド、Unityと色々手を出してる雑食系エンジニア。ReactNativeが最近のマイブーム。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

うえまつゆい エンジニア

サーバーサイドエンジニアからフロントエンドエンジニアになりました。主にReact Nativeでのアプリ開発をしています。

kobori

こぼり ともろう エンジニア

サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

sasai

ささい エンジニア

フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

damien

Damien

WebAR/VRを中心に企画やディレクションやエンジニアもちょっとやっています。森に住んでいます。

デザイナーゲスト

ゲスト デザイナー

CONTACT PAGE TOP