How to add a backdrop clickable overlay on official react-native Modal? - javascript

This is the official react-native modal documentation and this is a live example for iOS and Android.
How can I add a clickable backdrop overlay which is over my view and under the modal?

You can wrap the Modal content in a Touchable Opacity and style it with a background. I edited the sample given in the documentation.
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<TouchableOpacity
style={{ backgroundColor: 'black', flex: 1,justifyContent:'center' }}
onPress={() => setModalVisible(!modalVisible)}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: '#2196F3' }}
onPress={() => {
setModalVisible(!modalVisible);
}}>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</TouchableOpacity>
</Modal>

React Native Elements has a fantastic component called Overlay that would solve your problem. It saved me earlier this week. The only issue is that it is part of a larger library.
https://react-native-elements.github.io/react-native-elements/docs/overlay.html

I think if the separation between the backdrop and your modal is not crucial to your project, you can handle it like this:
<Modal
animationType="slide"
transparent={true}
style={{ width: '100%', alignSelf: 'center', height: '100%', justifyContent: 'flex-start' }}
visible={this.state.modalVisible}
onRequestClose={() => {
// Do smth
}}>
<TouchableWithoutFeedback style={{ flex: 1 }} onPress={() => {
// Do the backdrop action
}}>
<View style={{ backgroundColor: '#fff', flex: 1, width: '80%', height: '50%' }} >
<Text> Your content </Text>
</View>
</TouchableWithoutFeedback>
</Modal>

Related

"undefined is not an object", need to check if allNotes array is empty. How?

Feel like this is kind of a silly question but I need to only return the allNotes map data if allNotes isn't empty (its an array). This seems like just a simple if/else but really can't figure out how to do this in this context (inside view). Right now, I get the error in the title when nothing is in the array. when it has data everything is fine.
{isOpen &&
<TouchableOpacity onPress={() => updateDrop(prev => !prev)} style={styles.flastListUpdated}>
<View style={{ alignItems: 'center' }}>
<Text style={styles.flastlistItemText2}>{props.noteitem.note}</Text>
</View>
<View style={{ height: 1, width: '100%', backgroundColor: 'lightgrey' }} />
<View>
{allNotes.map((item) => {
return (
<View style={{ flexDirection: 'row', margin: 5 }}>
<View style={styles.perItemBar} />
<Text style={styles.noteTextStyle}>{item}</Text>
</View>
)
})}
<View style={styles.bottomBar}>
<TextInput onChangeText={(text) => { updateNoteStatus(text) }} style={{ flex: 2 }} placeholder='Enter New:' />
<TouchableOpacity onPress={addNote} style={{ flex: 1 }}>
<Text style={{ fontSize: 30 }}>+</Text>
</TouchableOpacity>
</View>
</View>
</TouchableOpacity>
}
</View>
)
}
Again I Know this is something really simple but I can't get the formatting correct. Don't know what the correct method of doing this would be. Thanks!
Could always double check that allNotes is defined like this although it may be better to default allNotes to an empty array and then confirm here that it's what you'd expect.
{isOpen &&
<TouchableOpacity onPress={() => updateDrop(prev => !prev)} style={styles.flastListUpdated}>
<View style={{ alignItems: 'center' }}>
<Text style={styles.flastlistItemText2}>{props.noteitem.note}</Text>
</View>
<View style={{ height: 1, width: '100%', backgroundColor: 'lightgrey' }} />
<View>
{allNotes && allNotes.map(item => (
<View style={{ flexDirection: 'row', margin: 5 }}>
<View style={styles.perItemBar} />
<Text style={styles.noteTextStyle}>{item}</Text>
</View>
)
)}
<View style={styles.bottomBar}>
<TextInput onChangeText={(text) => { updateNoteStatus(text) }} style={{ flex: 2 }} placeholder='Enter New:' />
<TouchableOpacity onPress={addNote} style={{ flex: 1 }}>
<Text style={{ fontSize: 30 }}>+</Text>
</TouchableOpacity>
</View>
</View>
</TouchableOpacity>
}
</View>
)
}

Button working on simulator but not in physical device

I'm trying to make use of the buttons on my app, but apparently they don't work on a physical device, I cannot press them. In the simulator it is indeed possible to press them, but not sure why not in the physical device.
This is the following code I'm using:
<ScrollView refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
}>
<View style={{ padding: 20, flexDirection: 'row' }}>
<TouchableOpacity onPress={() => console.log("the button works.")}>
<View style={styles.addHomework}>
<Text style={{ color: 'white' }}>Add Homework</Text>
</View>
</TouchableOpacity>
<View style={{ paddingLeft: 3 }}>
<TouchableOpacity onPress={() => this.removeSubject()}>
<View style={styles.removeSubject}>
<Text style={{ color: 'white' }}>Remove Subject</Text>
</View>
</TouchableOpacity>
</View>
</View>

How to create a backdrop component under a Flatlist?

I'm trying to invoke an action/event if a user pressed under a <FlatList /> component. Here's what I have so far:
. . .
return (
<View style={{ flex: 1 }}>
<FlatList
data={data}
renderItem={renderItem}
/>
<View style={{ flex: 300, width: Dimensions.get('screen').width, height: Dimensions.get('screen').height }}>
<TouchableWithoutFeedback
style={{
borderWidth: 1,
borderColor: 'white',
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').height,
}}
onPress={() => console.log('clicked')}
>
<Text>Backdrop button</Text>
</TouchableWithoutFeedback>
</View>
</View>
);
. . .
And this renders the follow:
It just seems too hacky for me, how can I get this to work better? I don't want to keep adding onto the flex value (in the code snippet, it is flex: 300) and I feel like I don't need Dimensions.
I got it to work like this:
. . .
return (
<View style={{ flex: 1 }}>
<View style={{ justifyContent: 'space-around' }}>
<View style={{ alignSelf: 'stretch' }}>
<FlatList
data={data}
renderItem={renderItem}
/>
</View>
</View>
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'stretch',
backgroundColor: 'blue',
}}
>
<TouchableWithoutFeedback
style={{
borderWidth: 1,
borderColor: 'white',
alignSelf: 'stretch',
width: Dimensions.get('screen').width,
height: '100%',
}}
onPress={() => console.log('clicked!')}
>
<Text style={{ color: 'white', fontWeight: 'bold' }}>Click me</Text>
</TouchableWithoutFeedback>
</View>
</View>
)
. . .
Neither sure if it's the best approach or if it will bring me problems in the future, but it seems to work for now. Looks like this:

How to display Icon in middle of screen in react native

Here, I am displaying "icon="check-decagram" type="MaterialCommunityIcons" in center, but its just coming in center and 20 padding from top. I have to display it middle of the mobile screen. I tried may be I am doing some wrong .Please correct me .
return(
<ImageBackground source={BG} style={styles.imgBG}>
<ScrollView>
<View>
<Header title={title} icon={icon} navigation={navigation} />
</View>
<View style={{ flexDirection: 'column', backgroundColor: '#ffff',}}>
<View style={{
flexDirection:'column', backgroundColor:'#fff',alignItems:'center',paddingTop:20,justifyContent: 'center'}}>
<IconXL icon="check-decagram" type="MaterialCommunityIcons" style={{ color: 'green' }}/>
</View>
<View style={{
flexDirection:'row', backgroundColor:'#ffff',padding:20,flexWrap:'wrap'}}>
<SmallText textColor="grey" text={`v${updateResponse.updateStatusList.currentAppVersion} `}/>
<SmallText textColor="grey" text={`${updateResponse.updateStatusList.desc}`}/>
</View>
</View>
</ScrollView>
</ImageBackground>
)}
// Thanks
try to add two more property height: '100%' and width: '100%' in superview of icon,
like,
<View style={{flexDirection:'column',height: '100%',width: '100%',backgroundColor:'#fff',alignItems:'center',paddingTop:2,justifyContent: 'center'}}>
<IconXL icon="check-decagram" type="MaterialCommunityIcons" style={{ color:'green' }}/>
</View>
Hope this works for you,
Good luck.
You can try something like.
<View style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'blue'
}}>
<Text style={{backgroundColor: 'red'}}>
Your Text
</Text>

How to solve margin problem between two components inside a Modal in React-Native?

In my react-native project inside modal, I am using two buttons in a View. But the problem is - no margin is working between them.
Here's the code
<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.ModalVisibleStatus}
onRequestClose={() => { console.log("Modal has been closed.") }}
>
{/*All views of Modal*/}
{/*Animation can be slide, slide, none*/}
<View style={styles.modal}>
<Text style={styles.text}>Modal is open!</Text>
<View style={styles.inputContainerEmail}>
<Image style={styles.inputIcon} source={{ uri: this.state.catImage }} />
<TextInput style={styles.inputs}
placeholder="Email Address"
keyboardType="email-address"
underlineColorAndroid='transparent'
onChangeText={(text) => this.updateValue(text, 'email')} />
</View>
<View style={{ flexDirection: 'row' }}>
<Button style={{ marginRight: 10 }} title="Save" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
<Button style={{ marginLeft: 10 }} title="Close" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
</View>
</View>
</Modal>
</View>
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DCDCDC',
},
modal: {
flex: 1,
alignItems: 'center',
backgroundColor: '#aaaa',
padding: 100
},
text: {
color: '#3f2949',
marginTop: 10
}
)}
After running these code it's getting following output-
So how can I add margin between these two buttons?
The React-Native Button is very limited in what you can do, and doesn't support a style property as far as I know. I would suggest looking into using TouchableOpacity or TouchableNativeFeedback to customize your needs.
A potentially dirtier solution would be to wrap both Buttons inside a separate individual parent View component and applying your margin property to these parent View components instead. Alternatively, you could perhaps specify justifyContent:'space-between' on your parent View Component as is and seeing if that gives the desired result too. For example, the multiple view approach might look something like the following:
<View style={{flexDirection: 'row'}}>
<View style={{flex:1 , marginRight:10}} >
<Button title="Save" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
</View>
<View style={{flex:1}} >
<Button title="Close" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
</View>
</View>
Hopefully that helps!
Add justifyContent:"space-between" in your button view code as
<View style={{ flex:1, flexDirection: 'row' , justifyContent:"space-between"}}>
<Button style={{ flex:1}} title="Save" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
<Button style={{ flex:2 }} title="Close" onPress={() => {
this.setState({ ModalVisibleStatus: !this.state.ModalVisibleStatus })
}} />
</View>
Link for reference https://css-tricks.com/almanac/properties/j/justify-content/

Categories