タブナビゲーション
モバイルアプリで最も一般的なナビゲーションスタイルは、おそらくタブベースのナビゲーションです。これは、画面の下部またはヘッダーの下(またはヘッダーの代わり)の上部にあるタブにすることができます。
このガイドでは、createBottomTabNavigator
について説明します。また、createMaterialBottomTabNavigator
およびcreateMaterialTopTabNavigator
を使用して、アプリケーションにタブを追加することもできます。
続行する前に、まず@react-navigation/bottom-tabs
をインストールしてください
- npm
- Yarn
- pnpm
npm install @react-navigation/bottom-tabs
yarn add @react-navigation/bottom-tabs
pnpm add @react-navigation/bottom-tabs
タブベースのナビゲーションの最小限の例
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
外観のカスタマイズ
これは、スタックナビゲーターをカスタマイズする方法と似ています。タブナビゲーターを初期化するときに設定されるプロパティと、options
で画面ごとにカスタマイズできるプロパティがあります。
// You can import Ionicons from @expo/vector-icons/Ionicons if you use Expo or
// react-native-vector-icons/Ionicons otherwise.
import Ionicons from 'react-native-vector-icons/Ionicons';
// (...)
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-information-circle'
: 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list' : 'ios-list-outline';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: 'tomato',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
詳しく見ていきましょう
tabBarIcon
は、ボトムタブナビゲーターでサポートされているオプションです。したがって、options
プロパティで画面コンポーネントで使用できることはわかっていますが、この場合は便宜上、アイコン構成を集中させるためにTab.Navigator
のscreenOptions
プロパティに配置することを選択しました。tabBarIcon
は、focused
状態、color
、およびsize
パラメーターが与えられる関数です。さらに構成を見ると、tabBarActiveTintColor
とtabBarInactiveTintColor
が表示されます。これらはデフォルトでiOSプラットフォームのデフォルトになりますが、ここで変更できます。tabBarIcon
に渡されるcolor
は、focused
状態(フォーカスされている場合はアクティブ)に応じて、アクティブまたは非アクティブのいずれかです。size
は、タブバーで想定されるアイコンのサイズです。createBottomTabNavigator
の構成オプションの詳細については、完全なAPIリファレンスをお読みください。
アイコンにバッジを追加する
アイコンにバッジを追加したい場合があります。tabBarBadge
オプションを使用して実行できます
<Tab.Screen name="Home" component={HomeScreen} options={{ tabBarBadge: 3 }} />
UIの観点からはこのコンポーネントはすぐに使用できますが、React Context、Redux、MobX、またはイベントエミッターを使用するなどして、バッジの数を適切に別の場所から渡す方法を見つける必要があります。
タブ間の移動
あるタブから別のタブへの切り替えは、おなじみのAPIであるnavigation.navigate
で行います。
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}
各タブのスタックナビゲーター
多くの場合、タブには1つの画面だけが表示されるわけではありません。たとえば、Twitterフィードでは、ツイートをタップすると、そのタブ内のすべての返信を含む新しい画面が表示されます。これは、各タブ内に個別のナビゲーションスタックが存在すると考えることができます。React Navigationでモデル化する方法はまさにこれです。
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator screenOptions={{ headerShown: false }}>
<Tab.Screen name="HomeStack" component={HomeStackScreen} />
<Tab.Screen name="SettingsStack" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
TabBarIOSまたは他のコンポーネントの代わりにTabNavigatorが必要なのはなぜですか?
アプリで使用しているナビゲーションライブラリに統合せずに、スタンドアロンのタブバーコンポーネントを使用しようとするのが一般的です。場合によっては、これで問題なく動作します。ただし、これを行うと、予期しない問題が発生してイライラする可能性があることに注意する必要があります。
たとえば、React NavigationのタブナビゲーターはAndroidのバックボタンの処理を自動的に行ってくれますが、スタンドアロンのコンポーネントは通常そうではありません。さらに、必要な場合に「このタブにジャンプしてからこの画面に移動する」などのアクションを実行する場合、2つの異なるAPIを呼び出す必要があるため、(開発者として)実行するのがより困難になります。最後に、モバイルユーザーインターフェイスには、特定のコンポーネントが他のコンポーネントのレイアウトまたは存在を認識する必要がある多数の小さな設計上の詳細があります。たとえば、半透明のタブバーがある場合、コンテンツはその下にスクロールする必要があり、スクロールビューには、コンテンツをすべて表示できるようにタブバーの高さと同じ下のインセットを設定する必要があります。タブバーをダブルタップすると、アクティブなナビゲーションスタックがスタックの最上部にポップし、もう一度行うと、そのスタックのアクティブなスクロールビューが最上部までスクロールする必要があります。これらの動作はすべてReact Navigationですぐに実装されるわけではありませんが、実装される予定であり、スタンドアロンのタブビューコンポーネントを使用すると、これらは何も得られません。