Before I start this modal, I have used modal from react-native, react-native-modal, and react-native-modalbox. But none of these modals has all the features I needed, so I created this modal
I haven't release it on npm yet, you may install this modal by
npm install --save git+https://github.com/zhantx/react-native-flex-modal.git
react-native-modalbox | react-native-flex-modal | react-native-modal | |
---|---|---|---|
Tap outside to close | yes | yes | not yet but close |
Swipe To Close | yes | yes | no |
Position | top, center, or bottom | anywhere | by changing style |
Control | methods or jsx prop | methods or jsx prop | jsx prop |
Where to use this component | has to be insisidede a full screen view (correct me if I'm wrong) | anywhere in jsx tree | anywhere in jsx tree |
Animation | slide from top or bottom | slide in from any position along with fading and zooming | powered by react-native-animatable |
Prop | Type | Default | Description |
---|---|---|---|
onCloes | func | Callback function, called modal is closed and animation is finished | |
onOpen | func | Callback function, called modal is opened and animation is finished | |
positionX | number | 0.5 | position of the modal, 0.5 means the modal is in horizontal center, 0 means the modal next to left edge of screen, 1 means the modal next to right edge of screen |
positionY | number | 0.5 | position of the modal, 0.5 means the modal is in vertical center, 0 means the modal next to top edge of screen, 1 means the modal next to bottom edge of screen |
backOpacity | number | 0.5 | Opacity of the underlay |
timeIn | number | 300 | Timing for the modal open animation (in ms) |
timeOut | number | null | Timing for the modal close animation (in ms), if it's null then it will use timeIn as default |
fadeIn | bool | false | set to true when you want your modal fade in |
fadeOut | bool | null | set to true when you want your modal fade out, if it's null then it will use fadeIn as default |
scaleIn | number | 1 | scale of the modal in the beginning of open animation |
scaleOut | number | 1 | scale of the modal in the end of close animation |
positionXIn | number | 0 | horizontal offset in the beginning of open animation |
positionXOut | number | null | horizontal offset in the end of close animation, if it's null then it will use positionXIn as default |
positionYIn | number | 0 | vertical offset in the beginning of open animation |
positionYOut | number | null | vertical offset in the end of close animation, if it's null then it will use positionYIn as default |
tapToClose | bool | true | set to false if you don't want the modal to close when user tap outside the modal |
backToClose | bool | true | set to false if you don't want the modal to close when user click back button(Android only) |
swipeable | bool | false | make the modal swipeable(don't use scrollView in modal if it's swipeable) |
swipeRangeX | array | [null,null] | horizontal range of the modal swipeable area,[-50,50] means the modal can only swipe 50 points to left or right, [0,0] means the modal can't be swipe horizontally, [null,null] means no limits horizontally |
swipeRangeY | array | [null,null] | vertical range of the modal swipeable area,[-50,50] means the modal can only swipe 50 points to up or down, [0,0] means the modal can't be swipe vertically, [null,null] means no limits vertically |
swipeThresholdX | array | [-50,50] | once the modal is dragged and released outside this threshold, the modal will close, [null,null] means no threshold horizontally |
swipeThresholdY | array | [-50,50] | once the modal is dragged and released outside this threshold, the modal will close, [null,null] means no threshold vertically |
inertia | bool | true | if the modal is closed by swiping, set to true will let modal keeps moving on that direction, false will let modal return to its designated position(positionXOut, positionYOut) |
containerSytle | object | style apply to the container of modal, made this props cuz I need to imply elevtion on Android |
|
isOpen | bool | Open/close the modal, optional, you can use the open/close methods instead |
I recommend use methods open()
and close()
to control this modal, this modal has tapToClose feature, when tapToClose is true
, the modal will close when tapping outisde despite the the value of isOpen
.
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
import Modal from 'react-native-flex-modal'
export default class Awesome extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<TouchableOpacity onPress={()=>this.modal.open()}>
<Text>Open</Text>
{/*
This modal doesn't require to be inside a full screen view
Can be anywhere in code
*/}
<Modal
ref={(modal)=>{this.modal=modal}}
positionX={0.3}
positionY={0.5}
timeIn={500}
fadeIn
scaleIn={0.3}
scaleOut={2}
positionXIn={200}
positionYIn={-200}
positionYOut={200}
swipeable
>
<View style={{ height: 100, width: 200, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center' }}>
<Text>
I am the modal
</Text>
</View>
</Modal>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('Awesome', () => Awesome);
positionX
is 0.3 so the modal is on the left, timeIn
is 500
to slow down the animation, I didn't set timeOut
it will be the same as timeIn
. scaleIn
is 0.3 the modal is scaling up from 0.3 to 1.
positionX
and positionY
are pretty handy if you wanna create a popover, you can set the position of modal based on button's position(use measure
)