so i've been doing react native for a while and after running my app on different devices all the components are not exactly what they are
this is an example :
import React from 'react';
import {StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#F5F5F8'
},
tinyLogo: {
width: 308,
height: 282,
resizeMode: 'contain',
alignSelf:'center',
top: 80
},
logo: {
width: 66,
height: 58,
},
text: {
textAlign: 'center',
color: "#2E3E5C",
fontSize: 22,
fontFamily: 'arial',
fontWeight: 'bold',
width: "100%",
marginTop:70
},
btnContainer: {
backgroundColor: "#CB5C17",
height: 60,
width:327,
borderRadius: 30,
justifyContent: 'center',
alignItems: 'center',
marginTop: 99
},
headline: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 100
}
});
const OnBoarding = ({ navigation }) => {
return (
<View style={ styles.container }>
<Image style={styles.tinyLogo}
source={require('../assets/TacosLogo.png')} />
<View style={styles.headline}>
<Text style={styles.text} >HOT AND FRENCH TACOS</Text>
<Text style={{ textAlign: 'center', color: "#9FA5C0", fontSize: 17, fontFamily: 'arial', fontWeight: 'bold', marginTop: 16, letterSpacing: 1 }} >The best taste</Text>
<TouchableOpacity activeOpacity={0.8} style={styles.btnContainer} onPress={() =>
navigation.navigate('Login')
}>
<Text style={{ color: 'white', fontSize: 15, fontWeight: 'bold', letterSpacing: 0.7, fontFamily: 'arial'}} >Commencer</Text>
</TouchableOpacity>
</View>
</View>
);
}
export default OnBoarding;
this is what it looks like on my android device Xiaomi Redmi 9 (6.53') 2340 x 1080 pixels
and this is what it looks like on other android device Huawei y6 (6.09') 1560 x 720 pixels
they dont look the same at all , even the dimensions
is there any solution for this ?
Try avoid spacing using hardcoded values like,
marginTop: 100,
marginTop: 99,
marginBottom: 70,
because you want your app to run on different device sizes.
Try Depending more on flexbox space-between and other alignment properties, rather than hardcoding the values.
Read more about it from here https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Or wrap the content in ScrollView component depending on the use case you have.
There is also some libraries that may help you by getting responsive values rather than hardcoded ones.
like: https://github.com/NewBieBR/react-native-normalize
https://github.com/marudy/react-native-responsive-screen#readme
Related
I'm developing an app using react native and Expo, and I'm having trouble with the keyboard on Android. When the keyboard pops up, it pushes the view up too much, causing the title to be cut in the middle. On iOS it's fine. I'd like to achieve the same behaviour..
I took a look at the docs, but it says that Android handles it automatically. But it's not doing it :/
Here is my code:
render() {
const { erroLogin, logando } = this.props;
return (
<ImageBackground style={styles.container} source={backgroundImage}>
<KeyboardAvoidingView
style={styles.keyboardViewContainer}
behavior={Platform.OS === 'ios' ? 'padding' : null}
>
<Text
style={{
fontFamily: 'roboto-bold',
color: '#ffffff',
fontSize: 48,
marginBottom: 20.7 * 3,
}}
>
Balad<Text style={{ fontFamily: 'roboto-light', color: '#ffffff', fontSize: 48 }}>APP</Text>
</Text>
<TextInput
value={this.state.email}
placeholder="Usuário"
style={[styles.input, { marginBottom: 4 * 3 }]}
placeholderTextColor="#828282"
maxLength={255}
autoCorrect={false}
keyboardType="email-address"
autoCapitalize="none"
returnKeyType="done"
underlineColorAndroid="transparent"
onChangeText={text => this.setState({ email: text })}
/>
<TextInput
value={this.state.senha}
placeholder="Senha"
style={styles.input}
placeholderTextColor="#828282"
maxLength={255}
autoCorrect={false}
autoCapitalize="none"
returnKeyType="done"
secureTextEntry
underlineColorAndroid="transparent"
onChangeText={text => this.setState({ senha: text })}
/>
<View style={styles.esqueceuView}>
<TouchableOpacity onPress={this.esqueciMinhaSenha}>
<Text style={styles.esqueceuSenha}>Esqueceu a senha?</Text>
</TouchableOpacity>
</View>
<CustomCheckBox style={styles.continuarConectadoView} onValueChange={this.switch} value={this.state.continuarConectado}>
<Text style={styles.continuarConectadoText}>Manter conectado</Text>
</CustomCheckBox>
<View style={{ height: 20 * 3, width: '80%' }}>
<Button
title="ACESSAR SISTEMA"
onPress={() => this.fazerLogin()}
titleStyle={styles.buttonText}
buttonStyle={styles.button}
loading={logando}
/>
</View>
</KeyboardAvoidingView>
{erroLogin && (
<View style={{ width: '80%', height: '10%', borderRadius: 1.7 * 3, marginTop: '5%' }}>
<ErrorBox
defaultMessage={
erroLogin.response.status === 401
? 'Email ou senha incorretos'
: 'Ops, houve um erro. Tente novamente'
}
/>
</View>
)}
<Text style={styles.versao}>{Constants.manifest.version}v</Text>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
keyboardViewContainer: {
width: '100%',
alignItems: 'center'
},
input: {
width: '80%',
height: 16.7 * 3,
borderRadius: 1.7 * 3,
fontSize: 4.7 * 3,
fontFamily: 'roboto-medium-500',
backgroundColor: '#ffffff',
paddingHorizontal: 6 * 3,
},
esqueceuView: {
width: '80%',
},
esqueceuSenha: {
fontFamily: 'roboto-medium-500',
letterSpacing: 0,
color: '#ffffff',
fontSize: 5 * 3,
marginTop: 8 * 3,
marginBottom: 8 * 3,
},
buttonText: {
fontFamily: 'roboto-medium-500',
color: '#ffffff',
fontSize: 4.7 * 3,
},
button: {
borderRadius: 1.7 * 3,
backgroundColor: '#de0059',
},
continuarConectadoView: {
flexDirection: 'row',
width: '80%'
// justifyContent: 'space-between'
},
continuarConectadoText: {
fontFamily: 'roboto-medium-500',
letterSpacing: 0,
color: '#ffffff',
fontSize: 5 * 3,
marginTop: 2 * 3,
marginBottom: 8 * 3,
marginLeft: 3 * 3
},
versao: {
color: '#ffffff',
fontFamily: 'roboto-regular',
fontSize: 16,
position: 'absolute',
top: '90%'
}
});
I posted the issue on the Expo forum and I got an answer.
All I had to do was to wrap the content inside the KeyboardAvoidView in a ScrollView and it worked. Still trying to figure it out why this is necessary, since the docs don't say anything about it.
Anyway, here is the link for the answer https://forums.expo.io/t/problems-with-keyboardavoidview/7799
I hope it helps other people.
There is a another workaround at the moment for SDK 37.
Just add this style code to the root View of a Screen:
{ minHeight: Math.round(windowHeight)) }
Then the keyboard will not resize the view.
import React from 'react';
import {
StyleSheet, View, useWindowDimensions,
} from 'react-native';
export default function AvoidViewMoving() {
const windowHeight = useWindowDimensions().height;
return (
<View
style={[{ minHeight: Math.round(windowHeight) }]}
>
{/* Your stuff */}
</View>
);
}
This idea was not mine. Credits go to this comment on GitHub from Ksedline:
https://github.com/expo/expo/issues/7589#issuecomment-629863678
This worked for me:
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
enabled={false}
style={styles.container}
>
... All your code.
</KeyboardAvoidingView>
);
For android add following line to the app.json android object
"softwareKeyboardLayoutMode": "pan",
Try to wrap everything inside your KeyboardAvoidingView inside a ScrollView
<KeyboardAvoidingView style={{ flex: 1}}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView>
//your container view is here
</ScrollView>
</KeyboardAvoidingView>
I have problem with styling of the Text, I have two lines of the Text, the first line of the text appears correct on the center of the row, but second line of the code, is not in the center. How to fix that?
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text
style={{ marginLeft: 5, fontWeight: '500', fontFamily: 'Arial', fontSize: ratio * 14, color: '#3c3c3c' }}
numberOfLines={2} > {title}
</Text>
</View>
You need to use textAlign:'center',
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
flexDirection: "row"
}}
>
<Text
style={{
textAlign:'center', //Added
marginLeft: 5,
fontWeight: "500",
fontFamily: "Arial",
fontSize: ratio * 14,
color: "#3c3c3c"
}}
numberOfLines={2}
>
{title}
</Text>
</View>
You just need to add textAlign in Text component
style={{textAlign: 'center', marginLeft: 5, fontWeight:'500',fontFamily: 'Arial', fontSize: ratio * 14, color:'#3c3c3c'}}
numberOfLines={2} >
Check snack demo here : https://snack.expo.io/SJyEEwM3b
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text
style={{ textAlign: 'center', marginLeft: 5, fontWeight: '500', fontFamily: 'Arial', fontSize: 1 * 14, color: '#3c3c3c' }}
numberOfLines={2} > some text some text some text some text some text some text some text some text
</Text>
</View>
);
}
}
I am learning RN and am practising layouts with flex. In the code below the View element with text LOGO appears in the 'footer' but does not render in 'header'.
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
export default class groceryApp extends Component {
constructor(props) {
super(props);
this.state = {text: 'myState'};
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
<View style={styles.leftbox}>
<Text>LOGO</Text>
</View>
</View>
<View style={styles.main}>
<View style={styles.box}><Text>111</Text></View>
<View style={styles.box}><Text>{this.state.text}</Text></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
</View>
<View style={styles.footer}>
<View style={styles.leftbox}>
<Text>LOGO</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center', // or 'space-between'
alignItems: 'stretch',
// 'flex-start', 'flex-end', 'stretch', 'center'
// for 'stetch' you have to remove fixed size from secondary from elements
},
header: {
height: 200,
backgroundColor: 'powderblue',
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start',
},
main: {
height: 450,
backgroundColor: 'skyblue',
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
flexWrap: 'wrap',
},
footer: {
height: 200,
backgroundColor: 'steelblue',
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start',
},
box: {
height: 100,
width: 100,
margin: 5,
backgroundColor: 'green',
},
leftbox: {
height: 50,
width: 50,
backgroundColor: 'green',
},
});
AppRegistry.registerComponent('groceryApp', () => groceryApp);
What am I missing here? The footer and header class seem identical so how is it different?
The Logo text is there...you just can't see it because of the Dimensions of the screen.
You are using fixed height dimensions within your flex containers...that is not ideal. The total screen height is less than all the heights you've declared. Stick to just flex, and not an absolute height for the containers.
change the style of header alignItems to flex-end and you shall see your text. Alternatively wrap your content in a ScrollView and you shall also see what is happening.
I have already read several flexbox tutorial, but I still cannot make this simple task to work.
How can I make the red box to 100% width?
Code:
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Natives
</Text>
<Text style={styles.line1}>
line1
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
style:
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
borderWidth: 1,
flexDirection: 'column',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
borderWidth: 1,
},
line1: {
backgroundColor: '#FDD7E4',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
borderWidth: 1,
},
Thank you!
Update 1:
Suggestion by Nishanth Shankar, adding
flex:1 for the wrapper,
flexDirection: 'row'
Output:
Code:
<View style={styles.container}>
<View style={{flex:1}}>
<Text style={styles.welcome}>
Welcome to React Natives
</Text>
</View>
<View style={{flex:1}}>
<Text style={styles.line1}>
line1
</Text>
</View>
<View style={{flex:1}}>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
</View>
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
borderWidth: 1,
flexDirection: 'row',
flexWrap: 'wrap',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
borderWidth: 1,
},
line1: {
backgroundColor: '#FDD7E4',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
borderWidth: 1,
},
Simply add alignSelf: "stretch" to your item's stylesheet.
line1: {
backgroundColor: '#FDD7E4',
alignSelf: 'stretch',
textAlign: 'center',
},
You should use Dimensions
First, define Dimensions.
import { Dimensions } from "react-native";
var width = Dimensions.get('window').width; //full width
var height = Dimensions.get('window').height; //full height
then, change line1 style like below:
line1: {
backgroundColor: '#FDD7E4',
width: width,
},
Editted:
In order to flex only the center text, a different approach can be taken - Unflex the other views.
Let flexDirection remain at 'column'
remove the alignItems : 'center' from container
add alignSelf:'center' to the textviews that you don't want to flex
You can wrap the Text component in a View component and give the View a flex of 1.
The flex will give :
100% width if the flexDirection:'row' in styles.container
100% height if the flexDirection:'column' in styles.container
Here you go:
Just change the line1 style as per below:
line1: {
backgroundColor: '#FDD7E4',
width:'100%',
alignSelf:'center'
}
First add Dimension component:
import { AppRegistry, Text, View,Dimensions } from 'react-native';
Second define Variables:
var height = Dimensions.get('window').height;
var width = Dimensions.get('window').width;
Third put it in your stylesheet:
textOutputView: {
flexDirection:'row',
paddingTop:20,
borderWidth:1,
borderColor:'red',
height:height*0.25,
backgroundColor:'darkgrey',
justifyContent:'flex-end'
}
Actually in this example I wanted to make responsive view and wanted to view only 0.25 of the screen view so I multiplied it with 0.25, if you wanted 100% of the screen don't multiply it with any thing like this:
textOutputView: {
flexDirection:'row',
paddingTop:20,
borderWidth:1,
borderColor:'red',
height:height,
backgroundColor:'darkgrey',
justifyContent:'flex-end'
}
Use javascript to get the width and height and add them in View's style.
To get full width and height, use Dimensions.get('window').width
https://facebook.github.io/react-native/docs/dimensions.html
getSize() {
return {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
}
}
and then,
<View style={[styles.overlay, this.getSize()]}>
width: '100%' and alignSelf: 'stretch' didn't work for me. Dimensions didn't suite my task cause I needed to operate on a deeply nested view. Here's what worked for me, if I rewrite your code. I just added some more Views and used flex properties to achieve the needed layout:
{/* a column */}
<View style={styles.container}>
{/* some rows here */}
<Text style={styles.welcome}>
Welcome to React Natives
</Text>
{/* this row should take all available width */}
<View style={{ flexDirection: 'row' }}>
{/* flex 1 makes the view take all available width */}
<View style={{ flex: 1 }}>
<Text style={styles.line1}>
line1
</Text>
</View>
{/* I also had a button here, to the right of the text */}
</View>
{/* the rest of the rows */}
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
just remove the alignItems: 'center' in the container styles and add textAlign: "center" to the line1 style like given below.
It will work well
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#F5FCFF',
borderWidth: 1,
}
line1: {
backgroundColor: '#FDD7E4',
textAlign:'center'
},
Style ={{width : "100%"}}
try this:
StyleSheet generated: {
"width": "80%",
"textAlign": "center",
"marginTop": 21.8625,
"fontWeight": "bold",
"fontSize": 16,
"color": "rgb(24, 24, 24)",
"fontFamily": "Trajan Pro",
"textShadowColor": "rgba(255, 255, 255, 0.2)",
"textShadowOffset": {
"width": 0,
"height": 0.5
}
}
Noted: Try to fully understanding about flex concept.
<View style={{
flex: 2,
justifyContent: 'center',
alignItems: 'center'
}}>
<View style ={{
flex: 1,
alignItems: 'center,
height: 50,
borderWidth: 1,
borderColor: '#000'
}}>
<Text>Welcome to React Nativ</Text>
</View>
<View style={{
flex: 1,
alignItems: 'center,
borderWidth: 1,
borderColor: 'red ',
height: 50
}}
>
<Text> line 1 </Text>
</View>
<View style={{
flex: 1,
alignItems: 'center,
height: 50,
borderWidth: 1,
borderColor: '#000'
}}>
<Text>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
</View>
Simply use width:'100%'
line1: {
backgroundColor: '#FDD7E4',
width: '100%'
},
I'm trying to place my icon on the same line as 2 Replies.
Here's a screenshot of how it looks:
I'd like to have it to the right of the line, as the arrow shows.
Here's how my Component's render function looks:
render: function() {
return (
<TouchableHighlight onPress={this.props.onSelect}>
<View style={styles.container}>
<Image source={{uri: this.state.image}}
style={styles.image} />
<View style={styles.postDetailsContainer}>
<Text style={styles.postTitle}>
{this.state.name}
</Text>
<Text style={styles.postDetailsLine}>
{this.state.comment}
</Text>
<View>
<Text style={styles.postChildrenDetails}>
{this.props.comment.child_comments_count} Replies
</Text>
<Icon
name='fontawesome|comments-o'
size={25}
color='#D6573D'
style={styles.icon}
/>
</View>
<View style={styles.separator} />
</View>
</View>
</TouchableHighlight>
)
}
Here's how my StyleSheet looks:
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFD',
},
image: {
height: 48,
width: 48,
borderRadius: 25,
marginTop: 10,
alignSelf: 'center',
marginRight: 15,
marginLeft: 15
},
postDetailsContainer:{
flex: 1,
},
postTitle: {
fontSize: 15,
textAlign: 'left',
marginTop: 10,
marginBottom: 4,
marginRight: 10,
color: '#D6573D'
},
postDetailsLine: {
fontSize: 12,
marginRight: 10,
color: 'gray',
},
postChildrenDetails: {
fontSize: 12,
marginTop: 5,
marginBottom: 10,
marginRight: 10,
color: 'gray',
textAlign: 'right',
flex: 1
},
separator: {
height: 0.5,
backgroundColor: '#CCCCCC',
},
icon: {
flex: 1,
textAlign: 'right',
width: 25,
height: 25
}
})
I had the same challenge and for anyone having the same issue, here is how I went about solving it.
Wrap the Icon and the Text in a View like #Colin Ramsey said above in the comments
It will look like this:
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Icon name="ios-chat" size={20} />
<Text>
2 replies
</Text>
</View>
Shalom!
TRY THIS
<View
style={{
backgroundColor: "#ffc8cc",
borderRadius: 30,
margin: 5,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingRight : 25
}}
>
<Text style={styles.title}>Leagues</Text>
<MaterialIcons name="sports-baseball" size={26} color="#cd000f" />
</View>
css for title :
title: {
fontSize: 18,
margin: 20,
color: "#cd000f",
},
Center image and text same line in props reactjs
<div style={{ alignItems: "center", display: "flex", justifyContent: "center" }} >
<img src={this.props.location.state.image} style={{ height: "100px", width: "100px", border: "4px solid white", verticalAlign: 'middle' }} />
<span style={{ fontSize: '40px', fontWeight: 'bolder', textAlign: 'center', verticalAlign: 'middle' }}>
{this.props.location.state.subject}</span>
</div>