モバイルアプリで最も一般的なナビゲーションのスタイルは、タブベースのナビゲーションでしょう。これは、画面下部のタブであったり、ヘッダー下の上部タブであったりします。
続行する前に、まず@react-navigation/bottom-tabsをインストールしてください。
npm install @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>
);
}
外観のカスタマイズ
これはスタックナビゲータをカスタマイズする方法と似ています。タブナビゲータを初期化するときに設定されるプロパティと、オプションで画面ごとにカスタマイズできるプロパティがあります。
import Ionicons from 'react-native-vector-icons/Ionicons';
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
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-box' : 'ios-list';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
解剖するために
tabBarIconは一番下のタブナビゲータでサポートされているオプションです。そのため、スクリーン・コンポーネントのプロパティで使用することができますが、今回は使いやすいようにアイコンを一元的に設定するために、Tab.NavigatorのscreenOptionsプロパティに置くことにしました。
tabBarIcon はフォーカスの状態、色、サイズのパラメータを与える関数です。設定のさらに下を見ると、tabBarOptions と activeTintColor と inactiveTintColor があります。これらのデフォルトは iOS プラットフォームのデフォルトですが、ここで変更することができます。tabBarIconに渡される色はアクティブまたは非アクティブの色です。サイズはタブバーのアイコンのサイズです。
## バッジをアイコンに追加
アイコンにバッジを追加したい場合があります。これを行う一般的な方法は、追加のビューコンテナを使用し、絶対配置でバッジ要素をスタイルすることです。
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>
);
}
タブ間のジャンプ
あるタブから別のタブへの切り替えには、おなじみのAPIであるnavigation.navigateがあります。
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/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 = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createStackNavigator();
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>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
各タブのスタックナビゲータ
例えば、Twitterのフィードでツイートをクリックすると、そのタブ内の新しい画面に移動し、すべての返信が表示されます。各タブの中に別々のナビゲーションスタックがあると考えることができ、これはまさにReact Navigationでモデル化されている方法です。
TabBarIOSや他のコンポーネントではなく、なぜTabNavigatorが必要なのですか?
アプリケーションで使用するナビゲーションライブラリに統合せずに、スタンドアロンのタブバーコンポーネントを使用しようとするのはよくあることです。場合によっては、これは素晴らしいことです! しかし、そうすると、イライラするような予期せぬ問題に遭遇することがあります。
例えば、React Navigationのタブナビゲータは、Androidの戻るボタンを処理してくれます。さらに、2つの異なるAPIを呼び出す必要がある場合、「このタブにジャンプして、この画面に移動する」といったアクションを実行するのは難しくなります。
例えば、半透明のタブバーがある場合、コンテンツはその下にスクロールされ、スクロールビューの下部にはタブバーの高さに等しいインセットがあり、すべてのコンテンツを見ることができます。タブバーをダブルクリックすると、アクティブなナビゲーションスタックがスタックの一番上にポップし、もう一度ダブルクリックすると、そのスタックのアクティブなスクロールビューが一番上にスクロールします。これらの動作のすべてが React Navigation ですぐに利用できるわけではありませんが、実装される予定です。