So I am just learning.... building a quiz app in react-native and I think the space between the first row of the buttons and the second row of the buttons is too much, how can I reduce it?
thanks
<LinearGradient colors={['#0D0B18','#28263E']} style={styles.container}>
<Text style={styles.question}>After Jesus rose from the dead, how long did he remain on earth before ascending to heaven? </Text>
<View style={styles.buttonRow}>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>12 days</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>40 days</Text>
</TouchableOpacity>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity style={styles.buttonStyle}onPress={this.onPress}>
<Text style={styles.buttonText}>3 months</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>1 year</Text>
</TouchableOpacity>
</View>
<View style={styles.progressStyle}>
<ProgressViewIOS
style={styles.progressView}
progress={(0.2)}
/>
</View>
</LinearGradient>
const styles = StyleSheet.create ({
container: {
flex: 3,
},
question: {
paddingTop: '20%',
padding: 30,
flex: 1,
color: '#fff',
fontSize: 25
},
buttonRow : {
marginTop: 0,
flexDirection: 'row',
color: '#fff',
alignItems: 'center',
justifyContent: 'space-evenly',
},
buttonStyle: {
backgroundColor: '#fff',
width: '40%',
height: '50%',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 10
},
buttonText: {
color: '#000'
},
progressView: {
width: '90%',
},
progressStyle: {
padding: 20,
alignItems: 'center',
justifyContent: 'center',
}
});
Small, you don't need flex: 3 for an element with no siblings, it shouldn't really matter but you only need to assign it flex: 1 if it is alone and should not take up more space relative to it's siblings.
To get your buttons to display nicely you should give them a wrapper:
<View style={styles.buttonWrapper}>
<View style={styles.buttonRow}>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>12 days</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>40 days</Text>
</TouchableOpacity>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>3 months</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle} onPress={this.onPress}>
<Text style={styles.buttonText}>1 year</Text>
</TouchableOpacity>
</View>
</View>
where styles.buttonWrapper is just:
buttonWrapper: {
flex: 1,
justifyContent: "space-around"
},
Now your button group and question will occupy an even amount of space after the height of your progress bar is taken into account and the button group will be squished together thanks to justifyContent: 'space-around'
This alters the size of the buttons however, so for this to work you should change the button styles to something like:
buttonStyle: {
backgroundColor: "#fff",
flex: 1,
marginHorizontal: 5,
aspectRatio: 2,
justifyContent: "center",
alignItems: "center",
borderRadius: 10
},
You can see this in action here: https://snack.expo.io/HkWF-EsA7
Flex can be a little weird when you're just starting out, so I recommend experimenting a lot. There are interesting properties like aspectRatio, alignContent, alignSelf and many others (learn more about those here). It may be frustrating at first but your layouts will be much better if you can avoid using width and height and entirely use flex instead. This isn't always possible but I think it will work just fine for what you're trying to accomplish.
I hope this gave you some idea of what you could do moving forward, if you have any questions let me know!
Related
React Native learner here.
I am trying to show the suggestions as below:
<TouchableOpacity
style={{
backgroundColor: 'transparent',
flexDirection: 'row',
flexWrap: 'wrap',
}}
onPress={() => {
setSelectedValue(item);
setFilteredFilms([]);
}}>
<View>
<Text style={styles.itemText}>{item.title}</Text>
<Button
title={'Click'}
style={{
backgroundColor: 'green',
right: 0,
paddingRight: 0,
marginRight: 0,
}}></Button>
</View>
</TouchableOpacity>
...
itemText: {
fontSize: 15,
paddingTop: 5,
paddingBottom: 5,
margin: 2,
alignItems: 'flex-start',
},
infoText: {
textAlign: 'center',
fontSize: 16,
},
Output looks like below:
I want my suggestion's Text in the left side, while Click button always at the right side fixed with fixed length.
Text and Button region shouldn't overlap each other.
Any help or guidance about how to do it. Highly appreciated !!
P.S.: With style={{flexDirection: 'row'}} in <View> my Buttons in Suggestion box get pushed to right side and not visible as below:
I expect something like this:
You have to use flexDirection:'row' for inner View which contain the Text and the Button
<TouchableOpacity
style={{
backgroundColor: 'transparent',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
}}
onPress={() => {}}>
<Text style={{ maxWidth: '90%' }}>
{item.title}
</Text>
<View>
<Text style={{ backgroundColor: 'blue', alignItems: 'center' }}>
Click
</Text>
</View>
</TouchableOpacity>
Don't forget to look at : https://www.npmjs.com/package/react-native-read-more-text
this will help you get through it.
Hello there guys
i have a problem with CSS in react native, i want to fit all my components in the screen without ScrollView but i cant seem to figure out what is my problem(i tried to change values for margins or paddings but it will look different in every device.)
As you can see at the attached image:
As you can see the graph below is not in the screen, i need to scroll view to the graph(which i dont want)
here is the code + css : (I dropped some lines to shorten the code(Like the carousel components and etc)
<View style={{ backgroundColor: "#fff" , flex: 1 }}>
<LinearGradient
colors={["#4c669f", "#3b5998", "#192f6a"]}
start={[0, 0]}
end={[1, 0]}
>
<View style={{ marginHorizontal: 20, paddingVertical: 48 }}>
<View style={styles.imageContainer}>
<View>
<View style={styles.check}>
<Ionicons name="md-checkmark" size={20} color={colors.pink} />
</View>
<Image
source={require("../assets/profile-pic.jpeg")}
style={{
width: 100,
height: 100,
borderRadius: 32,
}}
/>
</View>
</View>
<View style={[styles.center, { marginVertical: 12 }]}>
<Text style={styles.title}>
{currentUser.name + " " + currentUser.lastName}
</Text>
<Text style={[styles.subTitle, { marginTop: 8 }]}>
{businessDetails.bussinesName}
</Text>
</View>
</View>
</LinearGradient>
<View style={styles.container}>
<View style={styles.statContainer}>
<Text style={styles.statNumber}>1,700₪</Text>
<Text style={styles.stat}>הכנסה חודשית תופיע כאן</Text>
</View>
</View>
<View style={styles.center}>
<Text style={styles.textGraphTitle}>Graphs Analysis:</Text>
</View>
<View>
</View>
</View>
);
CSS:
center: {
alignItems: "center",
justifyContent: "center",
},
imageContainer: {
alignItems: "center",
justifyContent: "center",
marginTop: 1,
shadowColor: colors.darkBg,
shadowOffset: { height: 3, width: 1 },
shadowOpacity: 0.5,
},
container: {
paddingVertical: 24,
paddingHorizontal: 32,
marginBottom: 8,
backgroundColor: colors.lightBg,
flexDirection: "row",
justifyContent: "space-between",
marginHorizontal: 16,
borderRadius: 16,
marginTop: -48,
},
statContainer: {
alignItems: "center",
justifyContent: "center",
flex: 1,
},
You are asking responsive app design. Basically, you can use for width and height percentages or dimension.
import { Dimensions} from 'react-native'
const {width, height} = Dimensions.get('window')
One more approach is to use react-native-screens library
I have a screen where my data is displayed. I want to display in the form of table (The data at the bottom of screen)as shown below in screenshot.
Edited: top part code:
It's inside the movies as well
<View>
<Text key={item.symbol}>{item.symbol}<Text>
<Text key={item.open}>{item.open}<Text>
<Text key={item.close}>{item.close}<Text>
</View>
Right now my screen looks like:
I want to create an interface like below:
The data next to the close, high etc is some json data that I fetched from api.
My Code as of now :
let movie = (
<View style={styles.bottomdata}>
<Text style={styles.text} key={item.name}>
{item.name}
</Text>
<Text style={styles.text} key={item.open}>
OPEN {item.open}
</Text>
<Text style={styles.text} key={item.close}>
CLOSE{item.close}
</Text>
<Text style={styles.text} key={item.volumes}>
VOLUME{item.volumes}
</Text>
<Text style={styles.text} key={item.low}>
LOW {item.low}
</Text>
<Text style={styles.text} key={item.high}>
HIGH{item.high}
</Text>
</View>
)
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.container}>
<View>{movie}</View>
</View>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
text: {
color: "black",
backgroundColor: "white",
},
bottomdata:
{
marginTop:400,
backgroundColor:"black",
}
});
The movie is the data displayed on the screen. How do I design it like that? And, at the top it is just the symbol name (same as at the bottom) and close and high values. How can I design my screen like that? I am able to fetch the data but not sure how to design it like that.
You will have to use layout the contents using a views and test which would create something like a table. The below code shows how to position items in a row.
JSX
<View style={{ flex: 1 }}>
<View
style={{
flexDirection: 'row',
backgroundColor: 'black',
alignItems: 'center',
}}>
<Text style={{ flex: 0.5, color: 'white' }}>{item.symbol}</Text>
<Text style={{ flex: 0.5, color: 'white' }} key={item.open}>{item.open}</Text>
<Text
style={{
flex: 0.5,
color: 'white',
backgroundColor: 'red',
marginVertical: 5,
paddingHorizontal: 10,
borderRadius: 10,
}}
key={item.close}>
{item.close}
</Text>
</View>
<View style={styles.bottomdata}>
<Text style={[styles.text, { alignSelf: 'center' }]} key={item.name}>
{item.name}
</Text>
<View style={styles.row}>
<View style={styles.rowItem}>
<Text style={styles.text}>OPEN</Text>
<Text style={styles.text}>{item.open} </Text>
</View>
<View style={styles.rowItem}>
<Text style={styles.text}>CLOSE</Text>
<Text style={styles.text}>{item.close}</Text>
</View>
</View>
<View style={styles.row}>
<View style={styles.rowItem}>
<Text style={styles.text}>LOW</Text>
<Text style={styles.text}>{item.low} </Text>
</View>
<View style={styles.rowItem}>
<Text style={styles.text}>HIGH</Text>
<Text style={styles.text}>{item.high}</Text>
</View>
</View>
<View style={styles.rowItem}>
<Text style={styles.text}>VOLUME</Text>
<Text style={styles.text}>{item.volumes}</Text>
</View>
</View>
</View>
Styles
const styles = StyleSheet.create({
text: {
color: 'white',
},
bottomdata: {
marginTop: 'auto',
backgroundColor: 'black',
},
row: {
flexDirection: 'row',
width: '100%',
},
rowItem: {
width: '50%',
justifyContent: 'space-between',
flexDirection: 'row',
paddingHorizontal: 5,
},
});
You just need to make divs with some alignments and all and just get those data in the relavant field
I'm trying to create a layout that utilizes flexbox' automatic sizing but also contains fixed-size items:
<View style={{ height: 70, alignItems: "center" }}>
<Text style={{ flex: 1, textAlign: "right", paddingRight: 10 }}>left text</Text>
<Image style={{ width: 70, height: 70 }} src={require('./img.png')} />
<Text style={{ flex: 1, textAlign: "left", paddingLeft: 10 }}>right text</Text>
</View>
I want the image to be centered in the UI and have the text views equally take the remaining width. The actual result is that one of the text views is larger than the other as if the rendering doesn't take the width of the image view into account.
Finally found the correct way of doing this. To have fixed size items in a flex layout one shouldn't use width/height but flex: 0 and flexBasis. This approach initially didn't work for me because a component wrapping my component wasn't sized correctly and messed with the flex rendering. flexBasis seems to be density-independent pixels when it is set to an absolute number.
Proof of concept on expo.io
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
export default class App extends Component {
render() {
return (
<View>
<Text>Test</Text>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<Text>Test</Text>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
view: {
flex: 0,
flexBasis: 50,
height: 50,
backgroundColor: "red",
},
text1: {
flex: 1,
textAlign: "right",
paddingRight: 10,
},
text2: {
flex: 1,
textAlign: "left",
paddingLeft: 10,
}
});
I just want the Icon to be on the left and the text to be on center.
I have this structure:
<View style={styles.mainContainer}>
<Error screen={screen}/>
<View style={styles.headerContainer}>
{back &&
<Icon
raised
name='arrow-back'
onPress={ onBackPress }
containerStyle={styles.back}/>
}
<Text style={styles.header}>{ title }</Text>
</View>
<View style={styles.contentContainer}>
{ children }
</View>
</View>
Kinda like this:
-> MainContainer
--> HeaderContainer
----> Back button
----> Title
mainContainer: {
flex: 1,
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'flex-start'
},
headerContainer: {
flex: 1,
padding: 10,
flexDirection: 'row',
// ommited for clarity
},
back: {
alignSelf: 'flex-start'
},
header: {
fontSize: 24,
alignSelf: 'center'
},
But it doesnt work as it produces:
I also tried adding in HeaderContainer:
justifyContent: 'space-between',
and a blank <View />, but the result is not good:
As you can see, it's not centered really.
Edit Produces:
It's not really centered, because we put an imaginary thrid element. Can we do it with only two elemets? One in start and other on center?
Why is it not posible?
Try the following:
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
<View style={{ flex: 1 }}>
{leftContent}
</View>
<View style={{ flex: 1, alignItems: 'center' }}>
{centerContent}
</View>
<View style={{ flex: 1, alignItems: 'flex-end' }}>
{rightContent}
</View>
</View>
Don't forget to set textAlign: 'center' if center component is <Text> or textAlign: 'right' if the right component is Text.
Put your Icon and text in separate Views and asign a flex to it something like this
<View style={styles.mainContainer}>
<Error screen={screen}/>
<View style={styles.headerContainer}>
<View style={{flex:.3,alignSelf:'flex-start}}>
{back &&
<Icon
raised
name='arrow-back'
onPress={ onBackPress }
containerStyle={styles.back}/>
}
</View>
<View style={{flex:.7,alignSelf:'flex-end',alignItems:'center'}}>
<Text style={styles.header}>{ title }</Text>
</View>
</View>
<View style={styles.contentContainer}>
{ children }
</View>
</View>
I think it shoud fix the problem