Why is my modal height taking up half of the screen? - react-native

My modal -- noDevicesModalContainer -- is taking up an enormous amount of the screen and I can't work out why.
I am very new to React Native and web development generally, so please do not be afraid to overexplain!
Thank you in advance for your suggestions.
class DevicesEmptyScreen extends Component {
render() {
return (
<View style={styles.screen}>
<View style={styles.noDevicesImage}>
<Image
source={require('./../../../android/app/src/main/res/drawable/no_devices.png')}
/>
</View>
<View style={styles.noDevicesTextContainer}>
<Text style={styles.noDevicesText}>You do not have any devices yet</Text>
</View>
<View style={styles.noDevicesModalContainer}>
<Text style={[styles.noDevicesText, styles.noDevicesModalText]}>
In case no devices have been assigned, please contact your administrator
</Text>
</View>
</View>
)
}
}
export default DevicesEmptyScreen
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
noDevicesImage: {
flex: 1,
marginTop: 40
},
noDevicesTextContainer: {
flex: 1,
justifyContent: 'center'
},
noDevicesText: {
color: '#89C7C8',
padding: 10
},
noDevicesModalContainer: {
flex: 1,
backgroundColor: '#EBF5F6',
borderRadius: 10,
marginHorizontal: 30,
marginVertical: 30
},
noDevicesModalText: {
marginLeft: 20
}
})

As per Modal documentation. Try this
<Modal transparent={true}
visible={this.state.isVisible}
onRequestClose={this.closeModal}>
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'}}>
<View style={{
width: 300,
height: 300}}>
...
</View>
</View>
</Modal>

Related

How to define height to an element in react native in android?

I'm currently developing an app to be used in an Android tablet, unfortunately I got comfortable and added too many features in web view before testing again on android and now they look quite different.
I have a few elements in a flex-box view with flex-direction 'row', this is how they look on the browser and how they should look:
Then the same app on android looks like this:
You can see the two lines with inputs without proper height to fit the text, and a third line on the bottom already from another input.
This is the component code (I removed one input line to make it simpler):
<View>
<Text style={styles.header}>
{LanguageService(language).form.personalData}:
</Text>
<View style={styles.twoColumns}>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.firstName}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('firstName')}
value={formikProps.values.firstName}
maxLength={20}
/>
</View>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.phone}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('phoneNumber')}
value={formikProps.values.phoneNumber}
keyboardType='phone-pad'
maxLength={15}
/>
</View>
</View>
</View>
And here is the style:
const styles = StyleSheet.create({
twoColumns: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
},
inputWrapper: {
width: '48%',
flexDirection: 'row',
justifyContent: 'space-around',
borderBottomWidth: 1,
borderBottomColor: 'black',
margin: 10,
},
input: {
flexGrow: 1,
paddingLeft: 5,
},
header: {
color: 'red',
fontWeight: 'bold',
fontSize: 22,
},
}
I think you can achieve the shape in the first image with this structure:
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.header}>
{LanguageService(language).form.personalData}:
</Text>
</View>
<View style={styles.inputsContainer}>
<View stlye={styles.leftContainer>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.firstName}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('firstName')}
value={formikProps.values.firstName}
maxLength={20}
/>
</View>
</View>
<View stlye={styles.rightContainer>
<View style={styles.inputWrapper}>
<Text>
{LanguageService(language).form.phone}:
</Text>
<TextInput
style={styles.input}
onChangeText={formikProps.handleChange('phoneNumber')}
value={formikProps.values.phoneNumber}
keyboardType='phone-pad'
maxLength={15}
/>
</View>
</View>
</View>
</View>
Style:
const styles = StyleSheet.create({
container: {
display: 'flex',
flexDirection: 'column'
},
headerContainer: {
flex: 0.5
},
inputsContainer: {
flex: 1,
display: 'flex',
flexDirection: 'row'
},
leftContainer: {
flex: 1
},
rightContainer: {
flex: 1
}
inputWrapper: {
width: '48%',
flexDirection: 'row',
justifyContent: 'space-around',
borderBottomWidth: 1,
borderBottomColor: 'black',
margin: 10,
},
input: {
flexGrow: 1,
paddingLeft: 5,
},
header: {
color: 'red',
fontWeight: 'bold',
fontSize: 22,
},
}
I manage to solve this by removing the following line:
const styles = StyleSheet.create({
twoColumns: {
flex: 1,
}
}

Keyboard changing flex layout in react native with textInput

Layout overlapping on text input in react native as you can see in the images.
I have experimented with keyboardAvoidingView and keyboardAwareScrollView but I just cant fix it or I am implementing them incorrectly.
How to avoid keyboard from changing your flex layout? What's the industry standard? keyboardAvoidingView? I find that inconsistent or have not understood it conceptually. My approach usually is wrapping the entire code with either keyboardAwareScrollView or keyboardAvoidingView. Do I only do it over the textInput component?
const InterviewAlignment = ({navigation}) => {
return (
<View style={styles.container}>
<View style={styles.header}>
</View>
<View style={styles.main}>
<View
style={{
flex: 1,
justifyContent: 'space-between',
}}>
<View
style={{
flex: 1,
backgroundColor: 'red',
}}>
</View>
<View style={styles.modeContainer}>
</View>
<View style={{flex: 1}}>
<Text style={styles.text}>Link Address</Text>
<TextInput
style={styles.linkInput}
/>
</View>
</View>
<View style={{flex: 1, backgroundColor: 'red'}}>
</View>
<View style={{flex: 1.5, backgroundColor: 'black'}}>
</View>
</View>
</View>
);
};
//RFValue is just a responsive wrapper
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: RFValue(16),
minHeight: RFValue(56),
backgroundColor: '#B1C59B',
},
text: {
fontSize: RFValue(15),
color: 'black',
},
main: {
flex: 1,
padding: 15,
},
modeContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
flex: 1,
backgroundColor: 'yellow',
},
linkInput: {
marginHorizontal: RFValue(40),
padding: 0,
paddingTop: 2,
borderBottomWidth: RFValue(1),
borderBottomColor: '#C4C4C4',
},
});
You can set height instead of flex in styling

The image displayed in marker callout is cut

In my app, I want to display callout on a user clicks on the marker. I read that there are problems with displaying images in callout and a lot of people suggest placing the image in <Text> component [1,2,3]. For smaller images/icons this solution works, but I want to display one more "bigger" image, and here is an effect:
I don't know why this image has this "top margin" and why it is cut in the half. I was trying a lot of changes in the style of this Image and it's resizeMode but nothing is working. My other images in callout - like this icon on the bottom - had the same problem but adding a bigger size to the component in which there are placed help and everything looks fine. I was trying this solution on this big top image but it isn't working.
I will be grateful for any help and suggestions.
He is the Callout component code:
import { Dimensions, Image, StyleSheet, Text, View } from 'react-native'
import React, { Component } from 'react'
import { FontAwesome } from '#expo/vector-icons'
import PropTypes from 'prop-types'
import { colors } from '../constants/Colors'
const { width, height } = Dimensions.get('screen')
function getSpotDifficulty(spot) {
switch (spot.difficulty) {
case 0:
return 'DLA KAŻDEGO'
case 1:
return 'UMIARKOWANA'
case 2:
return 'DUŻA'
case 3:
return 'TYLKO DLA PROSÓW'
default:
return ' - '
}
}
function getSpotPopularity(spot) {
switch (spot.popularity) {
case 0:
return 'MALE'
case 1:
return 'SREDNIE'
case 2:
return 'DUŻE'
default:
return ' - '
}
}
const WATER_TYPE_FLAT_IC = require('../assets/images/ic_flat.png')
const WATER_TYPE_WAVE_IC = require('../assets/images/ic_wave.png')
const DIFFICULTY_EASY_IC = require('../assets/images/ic_flag_white_24.png')
const DIFFICULTY_HARD_IC = require('../assets/images/ic_flag_red_24.png')
export default class SpotMarkerCallout extends Component {
render() {
const marker = this.props.marker
const waterTypeIcon = marker.waterType === 0 ? WATER_TYPE_FLAT_IC : WATER_TYPE_WAVE_IC
const difficultyIcon = marker.waterType === 0 ? DIFFICULTY_EASY_IC : DIFFICULTY_HARD_IC
return (
<View style={styles.markerCallout}>
<Text >
<Image style={{flex: 1, height: 200}}
resizeMode={'cover'}
source={require('../assets/images/example_spot_photo.jpg')}/>
</Text>
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<View style={styles.markerHeader}>
<Text style={styles.spotNameText}>
{marker.name}
</Text>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<View style={styles.sportsIconsContainer}>
<View style={styles.singleInfo}>
<Text style={styles.textViewForIcon}>
<Image style={styles.sportIcon}
source={marker.windsurfing ? require('../assets/images/windsurfing_icon.png') : null}/>
</Text>
</View>
<Text style={styles.textViewForIcon}>
<Image style={styles.sportIcon}
source={marker.kitesurfing ? require('../assets/images/kitesurfing_icon.png') : null}/>
</Text>
<Text style={styles.textViewForIcon}>
<Image style={styles.sportIcon}
source={marker.surfing ? require('../assets/images/surfing_icon.png') : null}/>
</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'flex-end' }}>
<View style={[styles.singleInfo, { marginRight: 8 }]}>
<FontAwesome name="star" color={colors.ratingColor} size={10}/>
<Text style={{ marginRight: 4, color: colors.ratingColor }}>{marker.rating}</Text>
</View>
<View style={[styles.singleInfo, { marginRight: 8 }]}>
<FontAwesome name="location-arrow" color={colors.secondaryColor} size={10}/>
<Text style={{ marginRight: 4, color: colors.secondaryColor }}>{marker.distance} km</Text>
</View>
</View>
</View>
</View>
<Text style={styles.descriptionText} numberOfLines={3} ellipsizeMode='tail'>
{marker.description}
</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', marginVertical: 8 }}>
<View style={{ flex: 1, flexDirection: 'column', marginLeft: 4, }}>
<View style={styles.singleInfo}>
<Text style={styles.infoIconTextView}>
<Image style={styles.infoIcon} source={waterTypeIcon}/>
</Text>
<Text style={styles.infoText}>{marker.waterType === 0 ? 'FLAT' : 'WAVE'}</Text>
</View>
<View style={styles.singleInfo}>
<Text style={styles.infoIconTextView}>
<Image style={styles.infoIcon} source={require('../assets/images/ic_shaka_128.png')}/>
</Text>
<Text style={styles.infoText}>{marker.schools ? ' SZKOLENIA DOSTĘPNE' : 'BRAK SZKOLEN'}</Text>
</View>
</View>
<View style={{ flex: 1, flexDirection: 'column', marginLeft: 16, }}>
<View style={styles.singleInfo}>
<Text style={styles.infoIconTextView}>
<Image style={styles.infoIcon} source={difficultyIcon}/>
</Text>
<Text style={styles.infoText}>{getSpotDifficulty(marker)}</Text>
</View>
<View style={styles.singleInfo}>
<Text style={styles.infoIconTextView}>
<Image style={styles.infoIcon} source={require('../assets/images/ic_peoples.png')}/>
</Text>
<Text style={styles.infoText}>{getSpotPopularity(marker)}</Text>
</View>
</View>
</View>
</View>
)
}
}
SpotMarkerCallout.propTypes = {
marker: PropTypes.object.isRequired,
}
const styles = StyleSheet.create({
markerCallout: {
flex: 1,
width: width * 0.8,
flexDirection: 'column',
paddingLeft: 12,
justifyContent: 'space-around',
},
markerHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
},
spotNameText: {
fontSize: 22,
fontFamily: 'dosis_light',
textTransform: 'uppercase',
alignSelf: 'center',
},
sportsIconsContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
marginRight: 8,
},
singleInfo: {
flexDirection: 'row',
alignItems: 'center',
},
infoIcon: {
height: 18,
width: 18,
justifyContent: 'center',
alignItems: 'center',
},
infoIconTextView: {
height: 24,
justifyContent: 'center',
alignItems: 'center',
},
descriptionText: {
fontSize: 12,
color: colors.textBlackSecondaryColor,
paddingTop: 5,
},
sportIcon: {
height: 24,
width: 24,
},
textViewForIcon: {
height: 32,
},
infoText: {
fontSize: 10,
paddingLeft: 8,
justifyContent: 'center',
alignSelf: 'center',
},
})
And here is the code of usage:
<MapView.Callout onPress={() => this.props.navigation.navigate('SpotInfo', { chosenSpot: spot })}>
<TouchableHighlight>
<SpotMarkerCallout
marker={spot}/>
</TouchableHighlight>
</MapView.Callout>
</Marker>
i have notices you are using component change that to view
like
const newWidth = Dimensions.get('window').width
<View style={{ width: newWidth * 0.18, height: newWidth * 0.18 }}>
<Image style={{ width: newWidth * 0.18, height: newWidth * 0.18 }} source={require('your image path')} />
</View>
newWidth * 0.18 is the 18% width is the screen, change 0.18 to your desired percentage

How do I make one <View> take all available space when there is something else on the same row?

Im trying to make a flatlist with some data and a button on each row.
I have tried to do it in a typical "web" fashion, with nested views and formating the elements relative to their parent, but with no success.
this is the current structure of the list:
<View style={styles.row}>
<View style={styles.rowinfo}>
<View>
<Text style={styles.primaryID}>{item.name ? item.name : item.phoneNumber}</Text>
<Text style={styles.secondaryID}>{item.name ? item.phoneNumber : 'Ukjent innringer'}</Text>
</View>
<View>
<Text style={styles.textalignRight}>Varighet: {item.durationDisplay}</Text>
<Text style={styles.textalignRight}>{item.dateStringTime}</Text>
</View>
</View>
<TouchableOpacity style={styles.rowicon}>
<View style={styles.ban_icon}>
<Icon
name='ban'
type='font-awesome'
color='#FFF'
/>
</View>
</TouchableOpacity>
</View>
And here is my styling:
const styles = StyleSheet.create({
row: {
flex: 1,
marginTop: 1,
paddingVertical: 10,
paddingHorizontal: 15,
flexDirection: "row",
justifyContent: "space-between",
borderBottomWidth: 1,
borderBottomColor: '#f9f9f9'
},
rowinfo:{
flexDirection: "row",
alignSelf: 'stretch'
},
primaryID: {
fontWeight: 'bold'
},
textalignRight: {
textAlign: 'right'
},
rowbt: {
justifyContent: "center",
alignItems: "center",
backgroundColor: 'red'
},
ban_icon: {
color: '#FFF',
fontWeight: 'bold',
fontSize: 14,
marginHorizontal: 8
}
});
I im trying to make it look like this:
But i keep getting this:
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<View style={styles.rowinfo}>
<View>
<Text style={styles.primaryID}>{'Phone Number'}</Text>
<Text style={styles.secondaryID}>{'Ukjent innringer'}</Text>
</View>
</View>
<View style={{ flexDirection: 'row'}}>
<View>
<Text style={styles.textalignRight}>Varighet: {'1m og 20s'}</Text>
<Text style={styles.textalignRight}>{'13:23:11'}</Text>
</View>
<TouchableOpacity style={styles.ban_icon}>
<View style={styles.ban_icon} />
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
},
row: {
backgroundColor: 'green',
width: '100%',
marginTop: 1,
paddingVertical: 10,
paddingHorizontal: 15,
flexDirection: "row",
justifyContent: "space-between",
borderBottomWidth: 1,
borderBottomColor: '#f9f9f9'
},
rowinfo:{
flex: 1,
flexDirection: "row",
},
primaryID: {
fontWeight: 'bold'
},
textalignRight: {
textAlign: 'right'
},
ban_icon: {
padding: 10,
backgroundColor: 'red',
marginLeft: 10,
}
});
Check the snack: https://snack.expo.io/#legowtham/43c687
I was able to get my desired result by using absolute positioning.

React Native. How to place two Text with different fontSize in row with vertical align center

I need to align two Text component with different fontSize in a row and vertically centered. I have following now https://snack.expo.io/#troublediehard/dmVuZ2
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
row: {
flexDirection: 'row',
backgroundColor: 'red',
},
text1: {
fontSize: 20,
backgroundColor: 'blue',
},
text2: {
fontSize: 14,
backgroundColor: 'green',
},
});
For anyone that didn't found a solution yet, you have to wrap the text within another Text tag:
<View style={styles.container}>
<View style={styles.row}>
<Text>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</Text>
</View>
</View>
You need to add alignItems: 'center' to styles.row
row: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'red',
},