Previously, I was using toggling to handle navigation. Now I am switching to useNavigation hooks. From one page, I move to another page like this:
<TouchableOpacity
onPress={() => {
if (title == 'h') {
navigation.navigate('AddFriend');
}
}}>
When In navigate to the screen, I see an unwanted white space at the bottom, even though the original design did not have this. However, when I click the Cancelbutton, the space disappear, the page formats according to what it should be like and then it navigates back to the original page. Why is it showing the white space? How can I remove it?
This is how the code for my AddFriend page looks like:
type AddFriendPageProps = {
toggleShowPage: () => void;
showAddFriendPage: boolean;
};
export const AddFriendPage: React.FunctionComponent<AddFriendPageProps> = ({
toggleShowPage,
showAddFriendPage,
}) => {
const [showAddFriendPhonePage, setShowAddFriendPhonePage] = useState(false);
const navigation = useNavigation();
const toggleAddFriendPhonePage = () => {
setShowAddFriendPhonePage(showAddFriendPhonePage ? false : true);
};
return (
<Modal
visible={showAddFriendPage}
animationType="slide" transparent={true}>
<SafeAreaView>
<View style={styles.container}>
<View style={styles.searchTopContainer}>
<View style={styles.searchTopTextContainer}>
<Text
style={styles.searchCancelDoneText}
onPress={() => navigation.navigate('Home')}
>
Cancel
</Text>
<Text style={styles.searchTopMiddleText}>Add Friend</Text>
<Text style={styles.searchCancelDoneText}>Done</Text>
</View>
<View style={styles.searchFieldContainer}>
<View style={styles.buttonContainer}>
<Button
rounded
style={styles.button}
onPress={() => setShowAddFriendPhonePage(true)}>
<Text style={styles.text}>Add by Phone Number</Text>
</Button>
</View>
</View>
</View>
<AddFriendPhonePage
showAddFriendPhonePage={showAddFriendPhonePage}
toggleShowPage={toggleAddFriendPhonePage}
/>
</View>
</SafeAreaView>
</Modal>
);
};
Styles:
const styles = ScaledSheet.create({
container: {
height: '100%',
backgroundColor: 'white', //'#2E3331',
width: '100%',
},
searchTopContainer: {
backgroundColor: '#2E3331',
height: moderateScale(750),
},
searchTopTextContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginVertical: moderateScale(15),
height: moderateScale(30),
paddingLeft: moderateScale(30),
paddingRight: moderateScale(30),
},
searchCancelDoneText: {
fontSize: moderateScale(14),
color: 'white',
},
searchTopMiddleText: {
fontSize: moderateScale(15),
fontWeight: 'bold',
color: 'white',
},
searchFieldContainer: {
alignItems: 'center',
height: moderateScale(120),
},
button: {
width: moderateScale(200),
height: moderateScale(50),
backgroundColor: '#31C283',
justifyContent: 'center',
marginBottom: 20,
},
text: {
fontSize: moderateScale(14, 0.7),
},
searchField: {
backgroundColor: 'white',
width: moderateScale(300, 0.3),
height: verticalScale(40),
marginVertical: moderateScale(6),
borderRadius: verticalScale(10),
},
buttonContainer: {
paddingTop: 250,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-between',
},
inputText: {
color: '#ffffff',
},
searchText: {
fontSize: moderateScale(14),
},
});
If I change the background color the container to red and apply that style on the safeView, it makes the top part (where the time is written) red along with the bottom part which is supposed to match with the other screen. Both come under the safeView thing. How do I separate them?
If I remove the SafeView, the whole screen moves upwards, apart from the Cancel and Done button. The white space increases even more
that white space is added by safeAreaView. if you want the safeAreaView to have the same green background color you have to set the styles on it or it's parent, you currently only have styles on the child View element with the styles.container
I dont understand what you mean by 'how do i separate them'. basically, if you see the red color appear when you apply styles on the safeAreaView then instead of red use the gray/green color on the safeAreaView (that you're already using for the rest of the screen) so that it looks seamless.
Related
I have tried so many combinations of using containers that I don't know what else to do. Also, all the buttons must have equal dimensions, and the section of buttons must stretch to the end of the screen.
Start with a parentContainer with a row flexDirection so that items are laid left to right instead of up and down.
Add two views to parentContainer: imageContainer and buttonContainer. Divvy width among the two according to your layout desires (image from question suggest 50%/50%)
add centering styles to imageContainer and use onLayout to determine width and height of image.
add row flexDirection and flexWrap to buttonContainer.
Create a buttonStyle make sure it has width of 50%
Here's a snack that brings it all together:
import * as React from 'react';
import { Image, Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
const Button = ({ title, titleStyle, ...touchableProps }) => {
return (
<TouchableOpacity
{...touchableProps}
style={[styles.button, touchableProps.style]}>
<Text style={[{ textAlign: 'center' }, titleStyle]}>{title}</Text>
</TouchableOpacity>
);
};
export default function App() {
// used to set image size
const [{ width, height }, setViewDimensions] = React.useState({});
// update image size on imageview layout chagnes
const onLayout = ({ nativeEvent: { layout } }) => setViewDimensions(layout);
return (
<View style={styles.container}>
<View style={styles.parentContainer}>
<View style={styles.imageContainer} onLayout={onLayout}>
<Image
source={require('./assets/snack-icon.png')}
style={{ width, height: width }}
resizeMode="contain"
/>
</View>
<View style={styles.buttonContainer}>
<Button title="1" />
<Button title="2" />
<Button title="3" />
<Button title="4" />
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
parentContainer: {
flex: 1,
flexDirection: 'row',
},
imageContainer: {
width: '50%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'lightblue',
},
buttonContainer: {
width: '50%',
backgroundColor: 'lightgreen',
flexDirection: 'row',
flexWrap: 'wrap',
},
button: {
width: '50%',
alignItems: 'center',
justifyContent: 'center',
borderColor: 'white',
borderBottomWidth: 1,
borderRightWidth: 1,
},
});
I am adding image background to my app, but the horizontal part of the image went past the screen (the right and left part got cut). I tried to use resizeMode cover and contain but both of it didn't do anything. Is there any other way to make the image stay within the screen? (I use resizeMode on Image and it contain the image normally {same picture}).
import React from 'react';
import {
Image,
ImageBackground,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {DCTBACKGROUND} from '../../../assets/images';
export default function GetStarted({navigation}) {
return (
<ImageBackground source={DCTBACKGROUND} style={styles.page}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => {
navigation.navigate('Register');
}}>
<Text style={styles.buttonText}>Registrasi</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => {
navigation.navigate('Login');
}}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
</View>
</ImageBackground>
);
}
const styles = StyleSheet.create({
page: {
backgroundColor: '#90CC8B',
flex: 1,
paddingHorizontal: 15,
paddingVertical: 25,
// resizeMode: 'contain',
},
button: {
backgroundColor: 'yellow',
width: 100,
height: 40,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
},
buttonText: {
color: 'black',
},
buttonContainer: {
justifyContent: 'space-between',
flexDirection: 'row',
},
logo: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
});
The image horizontal part got cut a bit and I need to make it all show without being cut.
Add the resizeMode as a direct prop to the ImageBackground and not as part of the StyleSheet.
<ImageBackground resizeMode="contain" source={DCTBACKGROUND} style={styles.page}>
I know similar questions have been asked before but I couldn't fix this myself. I have an icon and a text that should be displayed on both ends of the screen. The icon should be at the left end while the text should be at the right end.
However, the Text extends the screen and is hidden from the right side, even if I add marginRight or paddingRight. How can I fix this?
export default function App() {
return (
<SafeAreaView style={styles.safeAreaViewContainer}>
<View style={styles.container}>
<View style={styles.topTextContainer}>
<BackArrow containerStyles={styles.arrowContainer} arrowStyles={styles.arrow}></BackArrow>
<Text style={styles.allFavoritePlaces}>Alle Lieblingsorts</Text>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
arrowContainer: {
marginTop: 0,
marginBottom: 0,
marginLeft: 0,
},
arrow: {
color: 'black',
paddingTop: 0,
},
allFavoritePlaces: {
alignItems: 'flex-end',
paddingRight: moderateScale(0),
paddingBottom: moderateScale(10),
},
topTextContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginVertical: moderateScale(15),
height: moderateScale(30),
paddingHorizontal: 20,
},
});
Here's a codesandbox too: https://snack.expo.io/#nhammad/sponaneous-candy
I opend it in the dev tools. The container of your arrow has some width assigned to it, when the screen gets to small it pushes the text out of the viewport.
I'm trying to change the background color of my app, but the color doesn't fill the whole screen. When I set flex to 0, the background color only spans the needed amount, but when I set it to 1, instead of expanding the whole screen, it shrinks. What did I do wrong?
Here's the code, changing the root view flex:
render() {
return (
<Text>{welcome}</Text>
<TextInput
underlineColorAndroid="rgba(0,0,0,0)"
placeholder={email}
autoCapitalize="none"
style={styles.textInput}
onChangeText={email1 => this.setState({ email1 })}
/>
<TextInput
underlineColorAndroid="rgba(0,0,0,0)"
secureTextEntry
placeholder={password}
autoCapitalize="none"
style={styles.textInput}
onChangeText={password1 => this.setState({ password1 })}
value={this.state.password1}
/>
{this.state.errorMessage && (
<Text style={styles.error}>{this.state.errorMessage}</Text>
)}
<TouchableOpacity
onPress={this.handleSignUp}
style={styles.buttonContainer}
>
<Text style={styles.buttonText}>{signup}</Text>
</TouchableOpacity>
<Text
style={styles.text}
onPress={() => this.props.navigation.navigate("LoginScreen")}
>
{already_have_an_account}
</Text>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
justifyContent: "center",
padding: 20,
backgroundColor: "red",
flex: 0
},
textInput: {
height: 40,
marginTop: 8,
paddingHorizontal: 8,
backgroundColor: "#e2e2e2"
},
buttonContainer: {
backgroundColor: "#3bd774",
padding: 15,
marginTop: 10
},
buttonText: {
textAlign: "center",
color: "white",
fontWeight: "bold"
},
logo: {
width: 200,
height: 200
},
logoContainer: {
alignItems: "center",
justifyContent: "center"
},
text: {
marginTop: 16,
color: "#bcbcbc",
textAlign: "center"
},
error: {
marginTop: 8,
color: "red"
}
});
You need to make sure you have flex:1 all the way down the chain of views. This is because flex: 1 will make the view fill its parent
I can see that what you have copy/pasted isn't all of the code, since there is a </KeyboardAvoidingView> but no opening tag.
So, at the very least you need a <KeyboardAvoidingView style={{flex: 1}}>, but if there is something wrapping that, you should add flex:1 to that control as well.
Put whole layout in a View wrapper and give this style to this view
container: {
justifyContent: "center",
padding: 20,
alignItems:'center',
backgroundColor: "red",
flex: 1
}
Running example: https://snack.expo.io/Hy-Gv-lGm
I have followed this post-React Native flex-box align icon and text to make a button with a title as below:
<View style={styles.sectionHeaderContainer}>
<Text style={styles.heading}>Work</Text>
<TouchableOpacity
style = {{width: 40, flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}
onPress={() => {
this.setState(previousState => {
Alert.alert('You tapped the button!')
});
}}>
<Image source={addIcon}/>
<Text style={styles.tertirayTitleDark}>Add Work</Text>
</TouchableOpacity>
</View>
the stylesheet is as below:
sectionHeaderContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-end',
paddingHorizontal: "6%",
paddingTop: "12%",
},
heading: {
fontSize: TITLE,
fontWeight: 'bold',
color: THEME_COLOR,
backgroundColor:'transparent',
},
tertirayTitleDark: {
fontSize: CONTENT_LARGE,
fontWeight: 'bold',
color: COLOR_DARK_PRIMARY,
},
However the button is taking all available horizontal space left by the title:
I have tried many different settings but still can't figure out what I'm doing wrong here.
Just remove flex:1. When you add flex:1 to the styles of the touchableOpacity you are exactly telling it to take all the available space and act just like the provided image. Hope this helps!
The accepted answer for me didn't work. Instead, I had to wrap the entire TouchableOpacity with a View with a given width, i.e.:
<View style={{width: yourDesiredWidth}}>
<TouchableOpacity>
// ...
</TouchableOpacity>
</View>