下から引っ張るような形のモーダル(Bottom Drawer)を実装する手順を紹介します。
イメージは以下のとおりです。
shell
npm i react-native-modal
react-native-modal
の swipeDirection
を 'down'
に設定すれば、下から引っ張るような動作にできます。
BottomDrawer.tsx
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Text, View, StyleSheet } from 'react-native';
import Modal from 'react-native-modal';
interface RegisterModalProps {
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
children?: React.ReactNode;
}
export default function BottomDrawer({ isOpen, setIsOpen, children }: RegisterModalProps) {
const toggleModal = () => {
setIsOpen(!isOpen);
};
return (
<Modal
isVisible={isOpen}
onBackButtonPress={toggleModal}
onSwipeComplete={toggleModal}
swipeDirection={'down'}
style={styles.bottomModal}
>
<View style={styles.modalContent}>
<View style={styles.modalCloseButton}>
<MaterialCommunityIcons name="close" size={24} color="black" onPress={toggleModal} />
</View>
{children}
</View>
</Modal>
);
}
const styles = StyleSheet.create({
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
modalContent: {
flex: 0.9,
backgroundColor: 'white',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 4,
borderColor: 'rgba(0, 0, 0, 0.1)',
},
modalCloseButton: {
position: 'absolute',
top: 10,
right: 10,
},
});
BottomDrawer
を使う側は、以下のように書けばOKです。
SampleScreen.tsx
import BottomDrawer from '../timeline/BottomDrawer';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { FAB } from 'react-native-paper';
export const SampleScreen = () => {
const [isOpen, setIsOpen] = React.useState(false);
return (
<View style={styles.container}>
<Text>ベースとなるスクリーンです。</Text>
<BottomDrawer isOpen={isOpen} setIsOpen={setIsOpen}>
<Text>モーダル</Text>
</BottomDrawer>
<FAB
style={styles.fab}
small
icon="menu"
onPress={() => {
setIsOpen(!isOpen);
}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#a29bfe',
alignItems: 'center',
justifyContent: 'center',
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
},
});