Reputation: 2311
Is it possible to close react native modal by clicking on overlay when transparent
option is true
? Documentation doesn't provide anything about it. Is it possible?
Upvotes: 102
Views: 173132
Reputation: 5615
If you want to close the modal when the user clicks outside of it, the only solution that I remember is:
render() {
if (!this.state.modalVisible)
return null
return (
<View>
<Modal
animationType="fade"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {this.setModalVisible(false)}}
>
<TouchableOpacity
style={styles.container}
activeOpacity={1}
onPressOut={() => {this.setModalVisible(false)}}
>
<ScrollView
directionalLockEnabled={true}
contentContainerStyle={styles.scrollModal}
>
<TouchableWithoutFeedback>
<View style={styles.modalContainer}>
// Here you put the content of your modal.
</View>
</TouchableWithoutFeedback>
</ScrollView>
</TouchableOpacity>
</Modal>
</View>
)
}
// Then on setModalVisible(), you do everything that you need to do when closing or opening the modal.
setModalVisible(visible) {
this.setState({
modalVisible: visible,
})
}
This is basically using a TouchableOpacity in the whole screen to get when the user clicks to close the modal. The TouchableWithoutFeedback is to avoid the TouchableOpacity to work inside of the Modal.
Upvotes: 190
Reputation: 690
Use TouchableWithoutFeedback and Modal of react-native:
<Modal
visible={visible} //modal visible true or false
onRequestClose={() => onClose(false)} // function to close modal
transparent={true}
>
<TouchableWithoutFeedback onPress={() => onClose(false)}>
//outer button/view
<View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)' }}>
//for transparent view, this is outer view
<TouchableWithoutFeedback>
// outer button so any child view can be added
<View>
// this inner view
<View>//your content goes here</View>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
If you want to add flatlist better to provide height so the content won't go out of view
Upvotes: 5
Reputation: 1
In double TouchableOpacity solutions if you are facing fading issues here is what you can do
<TouchableOpacity style={styles.modalContainer} activeOpacity={0} onPress={()=>{props.setModalVisible(false)}}>
<TouchableOpacity activeOpacity={1} style={styles.modalContent} >
Added activeOpacity on both lines first with 0 and the inner one as 1
Upvotes: 0
Reputation: 500
I just stumbled upon this thread and Gui Herzog's answer was exactly what I was looking for. If you don't want to add any outside dependencies that is the way to go.
However, I wanted to include some optional negative/positive action buttons in my component and grabbed them from react-native-paper for the material style. That's when I realized react-native-paper probably have modals as well.
Here's their documentation:
https://callstack.github.io/react-native-paper/modal.html
They also have a component for Dialogs
https://callstack.github.io/react-native-paper/dialog.html
So I ended up with using the paper Dialog and it's well worth if if you're going to use the library throughout you app. Both Dialog and Modal handles the dismiss on click outside by default.
Here's a Dialog component created before realizing the Dialog component already exists.
I'll leave what I implemented here anyways as I think its a good template.
The component is in typescript. Make sure to have @types/react-native
updated otherwise you might see some "No overload matches this call" errors.
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {Button, Modal, Portal} from 'react-native-paper';
interface Action {
action: () => void;
text: string;
}
interface Props {
closePressed: () => void;
negativeAction?: Action;
positiveAction?: Action;
title?: string;
text: string;
visible: boolean;
}
export const Dialog: React.FC<Props> = ({
closePressed,
negativeAction,
positiveAction,
title,
text,
visible,
}) => {
return (
<Portal>
<Modal
visible={visible}
onDismiss={closePressed}
contentContainerStyle={styles.modalContainer}>
<View style={styles.header}>
{title && (
<Text style={{fontWeight: 'bold', fontSize: 18, marginBottom: 10}}>
{title}
</Text>
)}
<Text style={styles.contentText}>{text}</Text>
</View>
<View style={styles.buttonContainer}>
{negativeAction && (
<Button mode="text" onPress={negativeAction.action}>
{negativeAction.text}
</Button>
)}
{positiveAction && (
<Button mode="text" onPress={positiveAction.action}>
{positiveAction.text}
</Button>
)}
</View>
</Modal>
</Portal>
);
};
const styles = StyleSheet.create({
modalContainer: {
borderRadius: 5,
backgroundColor: 'white',
padding: 10,
margin: 20,
},
header: {padding: 20},
contentText: {color: 'grey'},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
paddingTop: 20,
},
});
Upvotes: 0
Reputation: 164
Here is the solution.
import React,{useState} from 'react';
import{Button,StyleSheet,View,TouchableOpacity,Modal} from 'react-native';
const App=()=>{
const [show, setShow] = useState(false);
return (
<View>
<TouchableOpacity style={{marginTop:200}}>
<Button title='show' onPress={()=>setShow(!show)}/>
</TouchableOpacity>
<Modal transparent={true} visible={show} animationType="slide">
<TouchableOpacity activeOpacity={1} style={{backgroundColor:'#000000aa',flex:1}} onPress={()=>setShow(!show)}/>
<View style={{backgroundColor:'#FFFFFF',flex: 1}}>
<View >
<Button title='close' onPress={()=>setShow(!show)}/>
</View>
</View>
</Modal>
</View>
)};
export default App;
You can check another example here also:
https://snack.expo.dev/@saurabh_chavan/model-with-border-radius
Upvotes: 2
Reputation: 744
Instead of using TouchableWithoutFeedback
, native component called Pressable
allows you to check what you click on, therefore allows you to close only when clicked on it and not it's children.
return (
<View>
<Modal
animationType="slide"
transparent={true}
visible={visible}
onRequestClose={() => {
setVisible(false)}}
>
<Pressable
onPress={(event) => event.target == event.currentTarget && setVisible(false)}
style={styles.background}
>
<View style={styles.modal}>
//Content of the modal
</View>
</Pressable>
</Modal>
</View>
)
Found the answer here.
Upvotes: 18
Reputation: 271
You need one TouchableOpacity for clicking outside and another TouchableOpacity for actual modal that will do nothing onPress.
import { View, StyleSheet, TouchableOpacity, Modal} from 'react-native';
const Screen = () => {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(false) }
>
<TouchableOpacity style={styles.modalContainer} onPress={() => setModalVisible(false)} >
<TouchableOpacity style={styles.modal} activeOpacity={1} >
Modal Content...
</TouchableOpacity>
</TouchableOpacity>
</Modal>
</View>
)
}
const styles = StyleSheet.create({
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modal: {
width: 155,
height: 300
},
});
export default Screen;
activeOpacity={1} just removes touchableOpacity fade effect
Upvotes: 27
Reputation: 5200
Most of the answers here use <TouchableOpacity>
and/or <TouchableWithoutFeedback>
, which is fine, but as of 2023 there is a simpler implementation using the more modern <Pressable>
. Simply:
<Modal>
<Pressable onPress={() => handleOutsideModalClick()}>
<Pressable onPress={() => handleModalBodyClicks()}>
<Button onPress={() => handleButtonClicks()}>Option 1</Button>
<Button onPress={() => handleButtonClicks()}>Option 2</Button>
</Pressable>
</Pressable>
</Modal>
Upvotes: 0
Reputation: 133
Modal has a onBackdropPress prop. I found that to be the easiest fix.
Just realised I'm using a different Modal library. This is for react-native-modal
<Modal
isVisible={isVisible}
onBackButtonPress={() => closeModal()}
onBackdropPress={() => closeModal()}
onSwipeComplete={() => setIsVisible(false)}
swipeDirection={['down']}
scrollTo={handleScrollTo}
scrollOffset={scrollOffset}
scrollOffsetMax={300 - screenHeight}
propagateSwipe={true}
style={styles.modal}>
<OptionsModalContent
scrollViewRef={scrollViewRef}
handleOnScroll={handleOnScroll}
modalContent={modalContent}
setIsVisible={setIsVisible}
/>
</Modal>
Upvotes: 0
Reputation: 352
To Close a React Native Modal by clicking an Overlay is best done by using a Pressable button and TouchableOpacity
Example Below.
import React, { useState } from 'react';
import {
Pressable,
View,
Text,
TouchableOpacity,
ScrollView,
Modal,
TextInput,
StyleSheet,
} from 'react-native';
const [modalVisible, setModalVisible] = useState(false);
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<TouchableOpacity
onPress={() => setModalVisible(false)}
style={styles.modalContainerStyle}
>
<Pressable
onPress={() => setModalVisible(true)}
style={styles.modalContent}
>
<ScrollView>
<View>
<Text style={styles.modalTitle}>TITLE HERE</Text>
<Text style={styles.modalText}>
OTHER SMALLER TEXT HERE
</Text>
<Text style={styles.modalFormText}>AN INPUT</Text>
<TextInput
style={styles.modalInput}
value={inputValue}
onChangeText={(inputValue) => handleInputValue(inputValue)}
placeholder={'[email protected]'}
/>
<View style={styles.btnView}>
<TouchableOpacity
onPress={() => setModalVisible(!modalVisible)}
underlayColor="white"
>
<View style={styles.buttonProceed}>
<Text style={styles.buttonText}>NEXT</Text>
</View>
</TouchableOpacity>
</View>
</View>
</ScrollView>
</Pressable>
</TouchableOpacity>
</Modal>
<Pressable onPress={() => setModalVisible(!modalVisible)}>
<Text style={styles.openModal}>Open Modal</Text>
</Pressable>
modalContainerStyle: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'flex-end',
backgroundColor: 'rgba(0, 0, 0, 0.3)',
},
modalContent: {
borderTopLeftRadius: 27,
borderTopRightRadius: 27,
width: '100%',
height: '60%',
backgroundColor: '#FFFFFF',
paddingLeft: 33,
paddingRight: 33,
overflow: 'hidden',
},
modalTitle: {
marginTop: 43,
marginBottom: 14,
fontSize: 19,
lineHeight: 21,
color: 'black',
fontFamily: 'GraphikBold',
},
modalText: {
fontSize: 15,
lineHeight: 25,
marginBottom: 38,
color: 'black',
fontFamily: 'GraphikRegular',
},
modalFormText: {
marginBottom: 10,
fontSize: 15,
color: 'black',
fontFamily: 'GraphikMedium',
},
modalInput: {
marginBottom: 99,
height: 44,
paddingLeft: 17,
paddingRight: 17,
fontSize: 16,
borderRadius: 10,
marginBottom: 20,
borderWidth: 1,
fontFamily: 'GraphikRegular',
borderColor: 'rgba(118, 118, 118, 0.17)',
},
openModal: {
marginRight: 5,
textAlign: 'right',
color: '#ED2125',
fontFamily: 'GraphikMedium',
},
Upvotes: 0
Reputation: 472
Recently faced the issue, tried solving it using a two touchable opacity, you can also turn off the closing on tapping anywhere behaviour by passing the isDismissable value to false.
import { View, Text, Modal, StyleSheet, TouchableOpacity } from 'react-native';
import React from 'react';
type PropType = {
open: boolean;
onClose: () => void;
isDismissable?: boolean;
children: JSX.Element | JSX.Element[];
};
const styles = StyleSheet.create({
modalRootContainer: {
flexGrow: 1,
},
outerContainer: {
height: '100%',
},
});
const BottomModal = ({
open,
onClose,
isDismissable = true,
children,
}: PropType) => {
return (
<Modal
visible={open}
transparent
onRequestClose={onClose}
animationType='slide'
>
<TouchableOpacity
style={styles.outerContainer}
activeOpacity={1}
onPress={() => {
if (isDismissable) onClose();
}}
>
<View style={styles.modalRootContainer}>
<TouchableOpacity activeOpacity={1}>{children}</TouchableOpacity>
</View>
</TouchableOpacity>
</Modal>
);
};
export default BottomModal;
Upvotes: 0
Reputation: 754
@Gui Herzog answer are quite good, but makingTouchableOpacity
as a parent component, it deals with conflict when it comes touching child component.
it's not good practice having a multiple component inside of TouchableOpacity
, else all component inside TouchableOpacity
parent will be clickable, best way to address this problem is, make your TouchableOpacity
component in absolute position, with 100% width and height in screen.
Here's some example: Modal.js
export default function(props){
const { width, height } = Dimensions.get('window');
const hp = hp => (hp / 100) * height;
const wp = wp => (wp / 100) * width;
const size = size => Math.round((size / 100) * width);
return (
<KeyboardAvoidingView>
<TouchableOpacity
style={{ position: 'absolute', width: wp(100), height: hp(100) }}
onPress={props.onTouchOutSide}
/>
<ScrollView>
{/*...child*/}
</ScrollView>
</KeyboardAvoidingView>
)
}
Upvotes: 2
Reputation: 6677
I initial used the concept of wrapping Modal inside a Touchable opacity similar to the answer https://stackoverflow.com/a/40483972/1250311 but this would create touch issues when using ScrollView as a children.
So I moved to the second solution, which is nesting a absolute positioned overlay which covers the entire modal which on press will close the modal and then place the children inside this modal. Similar to https://stackoverflow.com/a/52936928/1250311 . Note, here I wrap the absolute positioned overlay and children, inside a parent View, to position the children to bottom or centre.
export function WFBottomSheetV2({
onRequestClose,
children
}) {
return (
<Modal
animationType='fade'
transparent={true}
visible
hardwareAccelerated
onRequestClose={onRequestClose}
>
<View style={styles.container} >
<TouchableWithoutFeedback onPress={onRequestClose} >
<View style={styles.modalOverlay} />
</TouchableWithoutFeedback>
{children}
</View>
</Modal>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center', // can also use 'flex-end' for bottomsheet style
alignItems: 'center'
},
modalOverlay: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,0,0,0.5)'
},
});
Upvotes: 0
Reputation: 685
You can install react-native-modal it's way more simpler and it has a property onBackdropPress just for this case
PS: it even has some animations which makes it look way better than the normal modal
Upvotes: 1
Reputation: 11
Would recommend the following which worked well for me:
<Pressable>
components inside the modalonPress
that closes the modal<Modal
animationType="slide"
transparent
visible={isModalVisible}
onRequestClose={() => setIsModalVisible(false)
>
<Pressable
onPress={() => setIsModalVisible(false)}
style={{flex: 1, opacity: 0}}
/>
<Pressable
style{{height: '25%', width: '100%', position: 'absolute', bottom: 0, justify-content: 'center', align-items: 'center'}}
>
<Text>Content of modal</Text>
</Pressable>
</Modal>
Upvotes: 0
Reputation: 71
*it's a very simple and effective solution I just applied it to my app and its works as I wanted. just wrap your child component into TouchableOpacity
EXAMPLE:
<Modal
animationType="slide"
transparent={true}
visible={IsCamaraShow}
onRequestClose={() => {
setIsCamaraShow(!IsCamaraShow);
}}>
<View style={Styles.centeredView1}>
<TouchableOpacity style={Styles.centeredView1}
onPress={()=> setIsCamaraShow(!IsCamaraShow)}
activeOpacity={1}
>
<View style={Styles.modalView1}>
{cosnole.log( 'rest of your code') }
</View>
</TouchableOpacity>
</View>
</Modal>
Upvotes: 0
Reputation: 1447
@idiosync/react-native-modal is a hook based modal system.
https://www.npmjs.com/package/@idiosync/react-native-modal
You can add a onBackgroundPress function to the config object to achieve what you want:
useModal(
{
// all config params are optional apart from renderModal
renderModal: () => <MyModal onClose={() => setModalIsVisible(false)} someProp={someProp} />,
onBackgroundPress: () => setModalIsVisible(false),
animationTypeIn: AnimationType.SLIDE_TOP,
},
modalIsVisible,
[someProp] // dependencies array to trigger rerenders. Empty array is passed by default
)
Upvotes: 0
Reputation: 109
I made it like this.
<Modal
visible={isVisible}
onRequestClose={() => setIsVisible(false)}
transparent={true}
>
<Pressable style={{
flex:1,
backgroundColor:'transparent',
}}
onPress={()=>setIsVisible(false)}
/>
{/* Here comes your component*/}
</Modal>
make your component with position:absoute
so Pressable
can cover the whole background.
Upvotes: 0
Reputation: 923
Another solution:
// Modal.js
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
Modal,
View,
} from 'react-native';
import t from 'prop-types';
class MyModal extends React.Component {
static propTypes = {
children: t.node.isRequired,
visible: t.bool.isRequired,
dismiss: t.func.isRequired,
transparent: t.bool,
animationType: t.string,
};
static defaultProps = {
animationType: 'none',
transparent: true,
};
render() {
const { props } = this;
return (
<View>
<Modal
visible={props.visible}
transparent={props.transparent}
onRequestClose={props.dismiss}
animationType={props.animationType}
>
<TouchableWithoutFeedback onPress={props.dismiss}>
<View style={styles.modalOverlay} />
</TouchableWithoutFeedback>
<View style={styles.modalContent}>
{props.children}
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
modalContent: {
flex: 1,
justifyContent: 'center',
margin: '5%',
},
modalOverlay: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,0,0,0.5)'
},
});
export default MyModal;
Usage example:
// SomeScreen.js
import React from 'react';
import { View, Text, Button } from 'react-native';
import Modal from './Modal';
class SomeScreen extends React.Component {
state = {
isModalVisible: false,
};
showModal = () => this.setState({ isModalVisible: true });
hideModal = () => this.setState({ isModalVisible: false });
render() {
return (
<View>
<Button onPress={this.showModal} />
<Modal
visible={this.state.isModalVisible}
dismiss={this.hideModal}
>
<Text>Hello, I am modal</Text>
</Modal>
</View>
);
}
}
Upvotes: 67
Reputation: 47
I have solved this in react native 0.64 by given below code
<Modal
isVisible={ModalVisible}
onBackdropPress={()=>{setModalVisible(false)}}
>
.
.
.
</Modal>
Upvotes: -1
Reputation: 1569
Here is my perfectly working solution
MODAL CODE:
const ListInModal = ({ showListModal, onClose, data, onSelectItem }) => {
return (
<Modal animationType="none" transparent={true} visible={showListModal} onRequestClose={() => onClose(false)}>
<TouchableOpacity onPress={() => onClose(false)} style={styles.centeredView}>
<View style={styles.modalView}>
<ScrollView showsVerticalScrollIndicator={false}>
{data.map((item, index) => (
<>
<TouchableOpacity
onPress={() => {
onSelectItem(item);
onClose(false);
}}
style={{ height: 43, justifyContent: 'center' }}
>
<Text style={styles.itemLabel}>{item.label}</Text>
</TouchableOpacity>
{index <= data.length - 2 && (
<View
style={{
borderBottomColor: colors.white,
opacity: 0.2,
borderWidth: 1,
marginHorizontal: (24 / 375) * screenWidth,
}}
/>
)}
</>
))}
</ScrollView>
</View>
</TouchableOpacity>
</Modal>
);
};
STYLING:
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#00000099',
},
modalView: {
marginHorizontal: wp('5%'),
marginVertical: hp('10%'),
backgroundColor: colors.popupBlack,
borderRadius: 20,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
itemLabel: {
fontSize: wp('5%'),
color: colors.white,
paddingHorizontal: (24 / 375) * screenWidth,
},
});
USAGE:
<ListInModal
data={projectState?.lvApplicationTypeList}
showListModal={showListModal}
onClose={(bool) => setshowListModal(bool)}
onSelectItem={(item) => onPressApplicationType(item.label)}
/>
Upvotes: 0
Reputation: 1054
Here is my solution,
import React from "react";
import {Modal, StyleSheet, TouchableOpacity, TouchableWithoutFeedback, View} from "react-native";
// make sure the styles props is passed to the model and contains modalContainer, as well as the childrenContainer style objects.
export default class DismissibleModal extends React.Component {
render() {
return (
<Modal
animationType="slide"
transparent={true}
visible={this.props.visible}
onRequestClose={() => {this.props.dismiss()}}>
<TouchableOpacity
style={Styles.modal}
activeOpacity={1}
onPressOut={() => {this.props.dismiss()}}>
<View style={[this.props.styles.modalContainer]}>
<TouchableWithoutFeedback>
<View style={[this.props.styles.childrenContainer]}>
{this.props.children}
</View>
</TouchableWithoutFeedback>
</View>
</TouchableOpacity>
</Modal>
)
}
}
const Styles = StyleSheet.create({
modal: {
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center'
},
modalView: {
backgroundColor: "white",
borderRadius: 10,
padding: 20,
paddingTop: 20,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 9,
},
shadowOpacity: 0.50,
shadowRadius: 12.35,
elevation: 19,
},
});
Upvotes: 2
Reputation: 143
If you are using store solution like mobx
or redux
,
you can simply solve with the flag on store.
Below is the parent's code,
<Modal
animationType="fade"
transparent={true}
visible={uiControlStore.dialogVisible}
onRequestClose={() => {
uiControlStore.dialogVisible = false;
}}
>
<View
style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.6)' }}
onTouchStart={() => {
if (!uiControlStore.childClicked) uiControlStore.dialogVisible = false;
uiControlStore.childClicked= false;
}}
>
<YourCustomDialog />
</View>
</Modal>
and below is child's code. (using mobx)
const YourCustomDialog: React.FC = observer(() => {
const { uiControlStore } = useStores();
return (
<View
style={[styles.container, styles.border]}
onTouchStart={() => {
uiControlStore.childClicked= true;
}}
>
...
)
}
Upvotes: 0
Reputation: 487
Simple solution with simple code, if you are using expo
.
Here is a complete component which can you just copy and paste and get it working.
//MyModal.js
import React from 'react';
import { BlurView } from 'expo-blur';
import { View, StyleSheet, Modal, TouchableWithoutFeedback } from 'react-native';
export const MyModal = ({ children, visible, onRequestClose, onPressOverlay, }) => {
return (
<Modal
visible={visible}
transparent
animationType='none'
onRequestClose={onRequestClose}
>
<TouchableWithoutFeedback onPress={onPressOverlay}>
<BlurView
style={{ ...StyleSheet.absoluteFill }}
tint='dark'
intensity={100}
/>
</TouchableWithoutFeedback>
<View style={styles.container}>
{children}
</View>
</Modal>
);
};
const styles = StyleSheet.create({
container: {
height: '100%',
width: '100%',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
});
Now you can import it into your work-space and use it like this.
I'm using functional component and useState
hook to show or hide the modal.
//yourScreen.js
import React, { useState } from 'react';
import { View, Button } from 'react-native';
import { MyModal } form './path/to/MyModal.js';
const YourScreen = () => {
const [modalVisible, setModalVisible] = useState(false);
return (
<View style={{ flex:1 }}>
<MyModal
visible={modalVisible}
onRequestClose={()=>{
setModalVisible(false);
}}
onPressOverlay={()=>{
setModalVisible(!modalVisible);
}}
>
// your modal content goes here
</MyModal>
<Button
title='Show Modal'
onPress={()=>{
setModalVisible(!modalVisible);
}}
/>
</View>
);
}
export default YourScreen;
Upvotes: 2
Reputation: 432
Here is my simple implementation:
<TouchableWithoutFeedback onPress={}> // Code to close your modal goes here
<View style={styles.background}> // The view to drawn the background
<View
onStartShouldSetResponder={() => true}
style={styles.container}
> // The view to drawn your modal
// Your content
</View>
</Androw>
</View>
</TouchableWithoutFeedback>
I use TouchableWithoutFeedback since i do not want to change the background color when clicking on it. I also added onStartShouldSetResponder on the modal view to prevent closing the modal when you click inside the view.
I am also not using the Modal component because i done it using react-navigation.
Upvotes: 8
Reputation: 1100
<Modal isVisible={this.state.isVisible}
onBackdropPress={() => this.setState({ isVisible: false })}>
<View style={{ flex: 1 }}>
<Text>I am the modal content!</Text>
</View>
</Modal>
Upvotes: 6
Reputation: 33
<Modal
animationType="slide"
closeOnClick={true}
transparent={true}
visible={this.state.modalVisible}
>
<TouchableOpacity onPress={() => { this.setModalVisible(!this.state.modalVisible)}} style={{flex:1, justifyContent:'center', alignItems:'center',}}>
<View style={{flex:0.2,backgroundColor:'white', margin:20, borderRadius:20, borderWidth:2, borderColor:'gray'}}>
<Text style={{margin:20}}>모달 테스트</Text>
</View>
</TouchableOpacity>
</Modal>
this code is my solution.
Upvotes: 3
Reputation: 3
Hi I am using a lightweight popup react-native-easypopup
it also closing itself when you tap out of popup.
npm i react-native-easypopup
Upvotes: -5
Reputation: 419
We can work it out by adding:
import { TouchableOpacity } from 'react-native';
<TouchableOpacity onPress={()=>this.setState({modalVisibilty:false})}>
<View style={{opacity:0, flex:1 }}/>
</TouchableOpacity>
under the window and another one above and change the layout style to fit your screen.
Explanation:
You will make 2 big hidden buttons to catch the user touch and change the modal visibility state to false.
Upvotes: 9