Multiple Rows Within Container - Flex - React-Native - css

First, I can't seem to set up a CodeSandBox - the following code in the index.js file just renders a blank screen: https://codesandbox.io/s/q4qymyp2l6
import React, { Component } from 'react';
import { View } from 'react-native';
export default class JustifyContentBasics extends Component {
render() {
return (
// Try setting `justifyContent` to `center`.
// Try setting `flexDirection` to `row`.
<View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<View style={{flex: 1, flexDirection: 'row', height: 50, backgroundColor: 'powderblue'}} />
<View style={{flex: 1, flexDirection: 'row', height: 50, backgroundColor: 'skyblue'}} />
<View style={{flex: 1, flexDirection: 'row', height: 50, backgroundColor: 'steelblue'}} />
</View>
);
}
};
But - if you copy and paste this code into the React-Native flexbox docs:
https://facebook.github.io/react-native/docs/flexbox
(first code sample under "LEARN MORE HERE") It will render three columns within a row.
I'm not understanding why. I've declared that the Views are rows with flexDirection: 'row', and they each get flex: 1, so I'd expect three equally sized rows.
With Bootstrap you can just declare a row within a container like so:
https://jsfiddle.net/HappyHands31/z0ncwe6b/
How can I achieve the same in React-Native?

You will put the contents of the code in the APP.JS file
If you give the COL value you get the result of 3 lines
flexDirection This is the direction in which the children inside the container will be
<View style={{
flex: 1,
flexDirection: 'col',//try change this line
justifyContent: 'space-between',
}}>

Related

Center elements within a view

I have a form component with some TextInput subcomponents as follows:
const FormComponent = () => {
return (
<View style={StyleSheet.container}>
<TextInput1/>
<TextInput2/>
<TextInput3/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
});
When i try to center align the form components using the StyleSheet, nothing seems to happen. I.e., the text inputs remain at the top left corner of the screen.
However, if I apply the styling directly to the View as follows:
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
then the textinput components become center aligned on the screen.
I dont understand why this is happening and would like to keep the code clean by using stylesheets to do this if possible.
Use styles instead of StyleSheet , that's a typo
<View style={styles.container}>
<TextInput1/>
<TextInput2/>
<TextInput3/>
</View>

Keyboard aware scroll view takes up screen space

I am implementing React Native Scroll View to handle the keyboard in my application layout, it works great but it is adding extra "padding" or whitespace below my components.
It is already styled with flex: 1 to take all the screen space. Here's the jsx code for App.js
<PaperProvider>
<StatusBar
barStyle="dark-content"
hidden={false}
backgroundColor="#00BCD4"
translucent={true}
/>
<KeyboardAwareScrollView
style={{ flex: 1 }}
>
<View style={styles.container}>
<UnitCard />
<UnitCard />
<Converter />
</View>
</KeyboardAwareScrollView>
</PaperProvider>
);
};
const styles = StyleSheet.create({
container: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
flex: 1,
backgroundColor: "#eee",
},
cards: {
flex: 1,
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
},
});
For anyone who comes later, the contentContainerStyle should have flex: 1 and then it should work, not the style property.
<KeyboardAwareScrollView
contentContainerStyle={{flex: 1}}
>
I don't think flex:1 will work in your KeyboardAwareScrollView or event in default React Native ScrollView
If you want to make it wrap all of your screen height, my suggestion is:
const SCREEN_HEIGHT = Dimensions.get("screen").height;
<KeyboardAwareScrollView
style={{ height: SCREEN_HEIGHT }}
>
....
Seems to have worked with the following code.
<KeyboardAwareScrollView
style={{ backgroundColor: "#4c69a5" }}
resetScrollToCoords={{ x: 0, y: 0 }}
contentContainerStyle={styles.container}
scrollEnabled={false}
style={{ height: Dimensions.get("window").height }}
automaticallyAdjustContentInsets={false}
>
... components
<KeyboardAwareScrollView/>
Taken from https://medium.com/free-code-camp/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580

I need an image to take up the maximum space it can regardless of its original size

I am developing a react-native application and I have a top bar and a bottom bar. There is an image between these two bars, and I need it to take up the maximum space it can regardless of the images original size without getting in the way of the two bars. I've been trying for a while and I can't figure out how to do this.
I have tried a bunch of things with flexbox and setting the image size, but I can't get it to work.
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import Topbar from './topbar.js'
export default function App() {
return (
<View style = {{
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between'
}}>
<View>
<Topbar />
</View>
<View>
<Image source={require('./image2.jpg')} />
</View>
<View>
<Topbar />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
// here are my bars
import React, { Component } from "react";
import {
Image, StyleSheet, View, Text,Dimensions
} from "react-native";
import Animated from "react-native-reanimated";
const {screenwidth, screenheight } = Dimensions.get("window");
export default class Topbar extends Component {
render() {
return (
<View style ={{
width: screenwidth,
height: 80,
backgroundColor: "#C0C0C0",
flexDirection: 'row',
justifyContent: 'space-between',
}}>
</View>
)
}
}
const styles = StyleSheet.create({
topbarbackground: {
width: screenwidth,
height: 80,
backgroundColor: "#C0C0C0",
}
})
I need to see the bars and the image and it has to take up the entirety of the phone screen.
I'm not pretty sure what you are trying to get. You can try using ImageBackground component and set the resizeMode to cover. Example:
Cover the entire Screen
<ImageBackground
source={img}
imageStyle={{ resizeMode: 'cover' }}
style={{ width: '100%', height: '100%' }}>
<Topbar/>
<View style={{ flex: 1 }}/>
<Bottombar/>
</ImageBackground>
Cover the available space
<View style={{ flex: 1 }}>
<Topbar/>
<ImageBackground
source={img}
imageStyle={{ resizeMode: 'cover' }}
style={{ width: '100%', flex: 1 }}/>
<Bottombar/>
</View>

Long text pushing other elements off screen with react native

I'm trying to build a layout in React-Native using Flexbox and I'm having trouble when the text is long. I want the layout to look like this:
However, when the blue text gets long, it pushes the date off of the right side of the screen like this:
I'm intentionally making the text stay on 1 line. What I want is for the blue text to expand as much as possible without making the text shrink. I'm new to RN and my work with CSS is very limited so I don't have much experience doing things like this. Here is my stylesheet code:
const styles = StyleSheet.create({
textContainer: {
flex: 1
},
separator: {
height: 1,
backgroundColor: '#dddddd'
},
title: {
fontSize: 25,
fontWeight: 'bold',
color: '#48BBEC'
},
subtitle: {
fontSize: 20,
color: '#656565'
},
dateContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end'
},
rowContainer: {
flexDirection: 'row',
padding: 10
}
});
And, finally, my layout code:
<TouchableHighlight
underlayColor='#dddddd'>
<View style={styles.rowContainer}>
<View cstyle={styles.textContainer}>
<Text numberOfLines={1} style={styles.title}>{rowData.name}</Text>
<Text style={styles.subtitle}>{rowData.teacher}</Text>
</View>
<View style={styles.dateContainer}>
<Text style={styles.subtitle}>{result}</Text>
</View>
<View style={styles.separator}/>
</View>
</TouchableHighlight>
Remove flex: 1 from dateContainer and add flexWrap: 'wrap' to textContainer.
textContainer: {
flex: 1,
flexWrap: 'wrap'
},
dateContainer: {
justifyContent: 'center',
alignItems: 'flex-end'
},
You'll have to set a width on the text component you wish to truncate (even if it's 100% of it's container which is the flexbox child I imagine), and also set numberOfLines prop to 1 (or however many lines you want to allow). See docs here on ellipsize mode and number of lines.
https://facebook.github.io/react-native/docs/text.html#ellipsizemode
Code example of what I explain above:
<View style={{display: 'flex', flexDirection: 'row', overflow: 'hidden'}}>
<View>
<Text
numberOfLines={1}
style={{width: '100%'}}>Text here that I want to truncate</Text>
<Text
numberOfLines={1}
style={{width:'100%'}}>Another line of text</Text>
</View>
<View style={{width: 120}}>
<Text>01/01/2017</Text>
</View>
</View>
If you're still having issues, it's possible you'll need to also use overflow: hidden in your text component style.
To solve your problem, remove the flex: 1 from the dateContainer and it won't go off the screen.
dateContainer: {
//flex: 1, line removed
justifyContent: 'center',
alignItems: 'flex-end'
},
Add the flex: 1 to your rowContainer as follows:
rowContainer: {
flex: 1, //Line added
flexDirection: 'row',
padding: 10
}
The solution to this is adding flexGrow: 0 to the element that is pushing others away.
I ended up solving this by measuring the parent view's width (with the onLayout callback) and then setting the width of the text's parent to the remainder.
This means having some state in the component, but it could be turned in to a general component with a left-side dynamic-sized component and a right-side static component.

React native text going off my screen, refusing to wrap. What to do?

The following code can be found in this live example
I've got the following react native element:
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
var SampleApp = React.createClass({
render: function() {
return (
<View style={styles.container}>
<View style={styles.descriptionContainerVer}>
<View style={styles.descriptionContainerHor}>
<Text style={styles.descriptionText} numberOfLines={5} >
Here is a really long text that you can do nothing about, its gonna be long wether you like it or not, so be prepared for it to go off screen. Right? Right..!
</Text>
</View>
</View>
<View style={styles.descriptionContainerVer2}>
<View style={styles.descriptionContainerHor}>
<Text style={styles.descriptionText} numberOfLines={5} >Some other long text which you can still do nothing about.. Off the screen we go then.</Text>
</View>
</View>
</View>);
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);
with the following styles:
var styles = StyleSheet.create({
container:{
flex:1,
flexDirection:'column',
justifyContent: 'flex-start',
backgroundColor: 'grey'
},
descriptionContainerVer:{
flex:0.5, //height (according to its parent)
flexDirection: 'column', //its children will be in a row
alignItems: 'center',
backgroundColor: 'blue',
// alignSelf: 'center',
},
descriptionContainerVer2:{
flex:0.5, //height (according to its parent)
flexDirection: 'column', //its children will be in a row
alignItems: 'center',
backgroundColor: 'orange',
// alignSelf: 'center',
},
descriptionContainerHor:{
//width: 200, //I DON\'T want this line here, because I need to support many screen sizes
flex: 0.3, //width (according to its parent)
flexDirection: 'column', //its children will be in a column
alignItems: 'center', //align items according to this parent (like setting self align on each item)
justifyContent: 'center',
flexWrap: 'wrap'
},
descriptionText: {
backgroundColor: 'green',//Colors.transparentColor,
fontSize: 16,
color: 'white',
textAlign: 'center',
flexWrap: 'wrap'
}
});
This results in the following screen:
How can I stop the text from going off the screen and keep it confined in the middle of the screen with a width of i.e. 80% of the parent.
I don't think I should use width because I will be running this on MANY different mobile screens and I want it to be dynamic, so I think I should rely totally on flexbox.
(That was the initial reason why I had flex: 0.8 within the descriptionContainerHor.
What I want to achieve is something like this:
Thank you!
I found solution from below link.
[Text] Text doesn't wrap #1438
<View style={{flexDirection:'row'}}>
<Text style={{flex: 1, flexWrap: 'wrap'}}> You miss fdddddd dddddddd
You miss fdd
</Text>
</View>
Below is the Github profile user link if you want to thank him.
Ally Rippley
Edit: Tue Apr 09 2019
As #sudoPlz mentioned in comments it works with flexShrink: 1 updating this answer.
The solution to that issue is flexShrink: 1.
<View
style={{ flexDirection: 'row' }}
>
<Text style={{ flexShrink: 1 }}>
Really really long text...
</Text>
</View>
Depending on your set up, you may also also need to add flexShrink: 1 to the <View>'s parent as well, to get this to work, so play with that and you'll make it.
The solution was discovered by Adam Pietrasiak in this thread.
This is a known bug. flexWrap: 'wrap' didn't work for me but this solution seems to work for most people
Code
<View style={styles.container}>
<Text>Some text</Text>
</View>
Styles
export default StyleSheet.create({
container: {
width: 0,
flexGrow: 1,
flex: 1,
}
});
you just need to have a wrapper for your <Text> with flex like below;
<View style={{ flex: 1 }}>
<Text>Your Text</Text>
</View>
This worked for me
<View style={{flexShrink:1}}>
<Text>some long random text...</Text>
</View>
Most of the times, we see this problem when using flexDirection: 'row' because in other case, it is handled properly.
Anyway, here are the two ways to wrap the text properly;
FIRST METHOD:
To wrap the text to next line and not leave the display, we can do so by restricting the width of the <Text>;
<Text style={{width: "60%"}}>some long text goes here ...</Text>
The above code will restrict the width of the text to 60% of the available width and if the whole text doesn't fit in that, it will wrap itself, i.e, remaining text will move to next line and so on.
SECOND METHOD
set flexShrink: 1 on both text element as well as its parent element which is wrapping it.
e.g,
<View style={{ flexShrink: 1, justifyContent: 'space-between', alignItems: 'center', flex: 1, flexDirection: 'row'}}>
<Text>First long string which goes long....</Text>
<Text style={{flexShrink: 1}}>This is a long long text which must go out of the screen if we dont style it properly and not do some logic here</Text>
</View>
Other styles are just to show that result is working properly. flexShrink: 1 is the only thing which you need.
Another solution that I found to this issue is by wrapping the Text inside a View. Also set the style of the View to flex: 1.
It works if you remove flexDirection: row from descriptionContainerVer and descriptionContainerVer2 respectively.
UPDATE (see comments)
I made a few changes to achieve what I think you're after. First of all I removed the descriptionContainerHor component. Then I set the flexDirection of the vertical views to row and added alignItems: 'center' and justifyContent: 'center'. Since the vertical views are now in fact stacked along the horizontal axis I removed the Ver part from the name.
So now you have a wrapper view that should vertically and horizontally align it's content and stack it along the x-axis. I then simply put two invisible View components on the left and right side of the Text component to do the padding.
Like this:
<View style={styles.descriptionContainer}>
<View style={styles.padding}/>
<Text style={styles.descriptionText} numberOfLines={5} >
Here is a really long text that you can do nothing about, its gonna be long wether you like it or not, so be prepared for it to go off screen. Right? Right..!
</Text>
<View style={styles.padding}/>
</View>
And this:
descriptionContainer:{
flex:0.5, //height (according to its parent),
flexDirection: 'row',
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center',
// alignSelf: 'center',
},
padding: {
flex: 0.1
},
descriptionText: {
backgroundColor: 'green',//Colors.transparentColor,
fontSize: 16,
flex: 0.8,
color: 'white',
textAlign: 'center',
flexWrap: 'wrap'
},
Then you get what I believe you were after.
FURTHER IMPROVEMENTS
Now if you would like to stack multiple text areas within the blue and orange views you can do something like this:
<View style={styles.descriptionContainer2}>
<View style={styles.padding}/>
<View style={styles.textWrap}>
<Text style={styles.descriptionText} numberOfLines={5} >
Some other long text which you can still do nothing about.. Off the screen we go then.
</Text>
<Text style={styles.descriptionText} numberOfLines={5} >
Another column of text.
</Text>
</View>
<View style={styles.padding}/>
</View>
Where textWrapis styled like this:
textWrap: {
flexDirection: 'column',
flex: 0.8
},
Hope this helps!
<View style={{flexDirection:'row'}}>
<Text style={{flex: 1, flexWrap: 'wrap'}}>
This will work
I had this same issue and to fix it I had to make sure ALL View parents had style={{flex: 1}}
I tried many of the answers above but none worked for me.
I achieved the best result by putting flexShrink on the Text element itself and flexGrow on both the parent View and the Text element.
I needed flexDirection: row on the parent because I want to have an icon on the right
<View style={flexDirection: 'row', flexGrow: 1}>
<Text style={
flexGrow: 1,
flexShrink: 1,
paddingLeft: 16,
paddingRight: 8,
alignItems: 'center',
}>
A long text that needs to wrap into multiple lines
</Text>
</View>
<Image source={rightArrow}/>
It looks like this:
In version 0.62.2 of React Native, i just put "flex-shrink: 1" in Container of my "Text", but remember the flex-direction:row in View of container. Thank you guys for the help.
My code:
export const Product = styled.View`
background: #fff;
padding: 15px 10px;
border-radius: 5px;
margin: 5px;
flex-direction: row;
`;
export const ProductTitleContainer = styled.View`
font-size: 16px;
margin-left: 5px;
flex-shrink: 1;
`;
export const ProductTitle = styled.Text`
font-size: 16px;
flex-wrap: wrap;
`;
`;
I wanted to add that I was having the same issue and flexWrap, flex:1 (in the text components), nothing flex was working for me.
Eventually, I set the width of my text components' wrapper to the width of the device and the text started wrapping.
const win = Dimensions.get('window');
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignSelf: 'center',
width: win.width
}}>
<Text style={{ top: 0, alignSelf: 'center' }} >{image.title}</Text>
<Text style={{ alignSelf: 'center' }}>{image.description}</Text>
</View>
I think you can do something like this, I have attached a picture with code for a better idea:
So, we can do something like this:
TermsOfService = {
fontFamily: 'Verlag-Book';
fontSize: 14px;
textAlign: center;
},
HighlightedText = {
font-family: 'Verlag-Book';
font-size: 14px;
text-align: center;
color: ${COLORS.PRIMARY_ADMIRAL_BLUE};
},
Container: {
width: 100%;
alignSelf: center;
alignItems: center;
justifyContent: center;
flexDirection: row;
flexWrap: wrap;
}
And is your Component just use it like this:
<View style={Container}>
<Text style={TermsOfService}>By joining, you agree to the some thing </Text>
<Text style={HighlightedText}>this is highlighted </Text>
<Text style={TermsOfService}>and </Text>
<Text style={HighlightedText}>and this as well</Text>
</View>
<View style={{flexDirection:'row'}}>
<Text style={{ flex: number }}> You miss fdddddd dddddddd
You miss fdd
</Text>
</View>
{ flex: aNumber } is all you need!
Just set 'flex' to a number that suit for you. And then the text will wrap.
Non of the answers work for me, so I decided to use a hack, which is to split the text by whitespace and render each of the word separately.
Although it's a hack, the upside is that I don't have to worry so much about messing up the wrapping due to the parent's container style.
// This code is written in Typescript
import React from 'react'
import { StyleSheet, View, Text } from 'react-native'
const styles = StyleSheet.create({
container: {
display: 'flex',
flexWrap: 'wrap',
flexDirection: 'row',
flex: 1,
justifyContent: 'center',
paddingVertical: 8,
},
})
export const WrapText: React.FC<{
text: string
}> = ({ text }) => {
return (
<View style={styles.container}>
{text.split(' ').map((word, index) => (
<Text key={index}>
{word}{' '}
</Text>
))}
</View>
)
}
const Example = <WrapText text="Hello this is a working hack that wraps your text."/>
P/S: Of course this only works for alphabetical writing systems, other writing systems that does not utilise spaces (e.g. Chinese writings) will not wrap using this component.
Unfortunately none of the above worked for me.
I found this npm package you could use the package directly:
https://github.com/Bang9/react-native-wrapped-text
Or create something similar like this:
<View style={{ alignItems: "center", alignSelf: "center", width: "100%" }}>
<View style={{ flexDirection: "row", flexWrap: "wrap"}}>
<Text style={{ textAlign: "center"}}>Long text, sooo looong...</Text>
</View>
</View>
Based on :
https://github.com/Bang9/react-native-wrapped-text/blob/master/src/index.js
Use height: 'auto' in text style.
Tried everything nothing worked but this ->
wrapText:{
width:"65%"
},
listItemLeft:{
fontWeight:"bold",
margin:3
},
<View style={styles.wrapText}>
<Text style={styles.listItemLeft}>{item.left}</Text>
</View>
<SafeAreaView style={{flex:1}}>
<View style={{alignItems:'center'}}>
<Text style={{ textAlign:'center' }}>
This code will make your text centered even when there is a line-break
</Text>
</View>
</SafeAreaView>
try to use this prop adjustsFontSizeToFit={true} in text component like this.
<Text adjustsFontSizeToFit={true}>
my solution below:
<View style={style.aboutContent}>
<Text style={[styles.text,{textAlign:'justify'}]}>
// text here
</Text>
</View>
style:
aboutContent:{
flex:8,
width:widthDevice-40,
alignItems:'center'
},
text:{
fontSize:widthDevice*0.04,
color:'#fff',
fontFamily:'SairaSemiCondensed-Medium'
},
result:
[
<Text style={{width: 200}} numberOfLines={1} ellipsizeMode="tail">Your text here</Text>

Resources