2018年6月29日
プログラミング
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 のような見た目のタブを作ってみました。
タブの下のメイン画面を左右にスワイプすると、上のタブナビゲーションも切り替わります。
もちろん、タブをタップするとその画面に遷移することができます。
実際のアプリ版Bageleeでは、 react-native-tab-view というライブラリを使用しており、もう少し複雑な実装になっています
それでは、コードを見ていきましょう!
先程の App.js
の RootStack
の定義の上に、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
こちらでは、navigation
のstate
の中身を取り出しています。
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でタブナビゲーションをカスタマイズする方法をご紹介しました!
このようにカスタマイズできると、アプリに合ったタブナビゲーションを実装できるのでとても良いですね。
ぜひ今回ご紹介したコードを参考に、タブナビゲーションをカスタマイズしてみてください。
React Nativeのお仕事に関するご相談
Bageleeの運営会社、palanではReact Nativeに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。
この記事は
参考になりましたか?
3
0
関連記事
2021年8月30日
React Navigation 6.0のStack Navigatorの大きく変わった箇所の変更点をまとめてみた
2021年1月4日
react-native-svgを使ってReact NativeでSVGを扱う
2019年12月23日
Expo Bare Workflow で Firebase Analytics を設定する
2018年12月6日
【React Native】キーボードで画面が隠れる場合の対処法
2018年7月13日
TypeScriptでReact Native開発をする方法2018年最新版
2018年6月29日
React Navigationのタブナビゲーションをカスタマイズしてみよう!
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへpalanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー
Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。
やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。
はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。
ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。
Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。
ゲスト bagelee
かっきー
まりな
suzuki
miyagi
ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。
いわもと
デザイナーをしています。 好きな食べ物はラーメンです。
taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。
kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya
aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。
Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています
sugimoto
asama
ando
iwasawa ayane
oshimo
異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!