Modal
モーダルは、メインコンテンツを一時的にブロックして別のコンテンツを表示します。ポップアップと似たような性質を持ち、通常の画面遷移とは異なる方法でコンテンツを表示します。
モーダル画面のナビゲータ定義にもStackNavigator
を用います。
StackNavigator
のscreenOptions.presentation
プロパティに'modal'
を指定すると、モーダル表示の画面アニメーションが実現できます。
ネストされたナビゲータ
モーダルコンテンツは全てのメインコンテンツに優先して表示させるため、一般的にネストされたナビゲータを用いて定義します。
次の図は、Modal 1
をモーダルとして定義した場合のナビゲータ構成です。
RootStack
はMainStack
を子ナビゲータとして定義しています。
このナビゲータ構成のコード例は次の通りです。
const RootStack = createStackNavigator();
const MainStack = createStackNavigator();
export const App = () => {
return (
<NavigationContainer>
<RootStack.Navigator screenOptions={{headerShown: false, presentation: 'modal'}}>
<RootStack.Screen name="MainStack" component={Main} />
<RootStack.Screen name="Modal1" component={Modal1} />
</RootStack.Navigator>
</NavigationContainer>
);
};
const Main = () => {
return (
<MainStack.Navigator>
<MainStack.Screen name="Screen1" component={Screen1} />
<MainStack.Screen name="Screen2" component={Screen2} />
</MainStack.Navigator>
);
};
RootStack.Navigator
タグの中でscreenOptions.presentation
プロパティに'modal'
を指定しています。
これにより、Modal1
への画面遷移はモーダル表示のアニメーションとなります。
React Navigation公式ドキュメントのOpening a full-screen modalに次の記載があります。
The modal prop has no effect on Android because full-screen modals don't have any different transition behavior on the platform.
画面遷移アニメーションは、各プラットフォームのネイティブ動作に従います。
上記のとおり、Androidのフルスクリーンモーダルには異なるトランジションが用意されていないため、presentation
属性の変更によるアニメーションの変更はありません。
ネストされたナビゲータは次のように動作します。
- 各ナビゲータは独自のナビゲーション履歴を保持する
- 各ナビゲータ毎に独自のオプションを定義できる
- ナビゲーション操作は現在のナビゲータによって処理され、処理できなかった場合は上位のナビゲータに処理を移譲する
- 親ナビゲータのUIは、子ナビゲータの上に描画される
- 画面イメージ
- ソースコード
import {
NavigationContainer,
useNavigation,
} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
import {Text, View, StyleSheet} from 'react-native';
import {Button} from 'react-native-elements';
const RootStack = createStackNavigator();
const MainStack = createStackNavigator();
export const App = () => {
return (
<NavigationContainer>
<RootStack.Navigator screenOptions={{headerShown: false, presentation: 'modal'}}>
<RootStack.Screen name="MainStack" component={Main} />
<RootStack.Screen name="Modal1" component={Modal1} />
</RootStack.Navigator>
</NavigationContainer>
);
};
const Main = () => {
return (
<MainStack.Navigator>
<MainStack.Screen name="Screen1" component={Screen1} />
<MainStack.Screen name="Screen2" component={Screen2} />
</MainStack.Navigator>
);
};
const Screen1: React.FC = () => {
const navigation = useNavigation();
return (
<View style={styles.screen}>
<Text style={styles.title}>Screen 1</Text>
<Button
buttonStyle={styles.button}
title="Navigate Screen 2"
onPress={() => navigation.navigate('Screen2')}
/>
<Button
buttonStyle={styles.button}
title="Popup Modal 1"
onPress={() => navigation.navigate('Modal1')}
/>
</View>
);
};
const Screen2: React.FC = () => {
const navigation = useNavigation();
return (
<View style={styles.screen}>
<Text style={styles.title}>Screen 2</Text>
<Button
buttonStyle={styles.button}
title="Go Back"
onPress={() => navigation.goBack()}
/>
<Button
buttonStyle={styles.button}
title="Popup Modal 1"
onPress={() => navigation.navigate('Modal1')}
/>
</View>
);
};
const Modal1: React.FC = () => {
const navigation = useNavigation();
return (
<View style={styles.screen}>
<Text style={styles.title}>Modal 1</Text>
<Button
buttonStyle={styles.button}
title="Close"
onPress={() => navigation.goBack()}
/>
</View>
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center',
},
title: {
padding: 20,
fontSize: 42,
},
button: {
margin: 10,
width: 200,
},
});
React Navigation v5では、画面単位ではモーダル表示を設定できず、モーダル表示のために専用のナビゲータが必要でした。v6で導入されたGroup
を使うことで、モーダル表示の画面と非モーダル表示の画面を、両方とも同じナビゲータの中に配置できます。
Group
を使ったモーダル表示の方法については、Opening a full-screen modal | React Navigationを参照してください。