React Native Text component overflows parent when inside with another view - react-native

I have a text component which is contained within a parent of a set width alongside a small black box to its right. My question is why does the text elipsise only when it reaches the end of the parent container when the black box (its sibling) is pushed out? How can I make the text respect the space of its sibling and elipsise earlier?
<View style={{height: 30, width: 200, flexDirection: "row", borderWidth: 1}}>
<Text numberOfLines={1}>
{"This is a very very very long sentence that is meant to elipsize"}
</Text>
<View style={{width: 20, height: 20, backgroundColor: "black"}} />
</View>
This is what this result looks like

In React Native, a Text component does not behave according to the box model. So it shrinks and expands according to its need, given the dimensions of the parent component (and sometimes overflowing it depending on the styling).
An easy fix in such case is to wrap the Text component in its own view.
Setting the Text component width will also work.

Just you need to wrap the Text component into a View with { flex: 1 } style. It should help:
<View style={{height: 30, width: 200, flexDirection: "row", borderWidth: 1}}>
<View style={{flex: 1}}>
<Text numberOfLines={1}>
{"This is a very very very long sentence that is meant to elipsize"}
</Text>
</View>
<View style={{width: 20, height: 20, backgroundColor: "black"}} />

Related

ScrollView on material-bottom-tabs not working

Current Behavior
I'm creating my tabs like this (note: Home is a StackNavigator screen):
ProfileTab is rendered this way (items is an array of inputs):
return <ScrollView contentContainerStyle={{flex: 1, backgroundColor: Colors.primaryShade3,
paddingTop: Sizes.paddingTop}}>
<View style={{flexDirection: "row", alignItems: "center", marginBottom: 50}}>
<Image source={{uri: RNStorage.userProfile.user.photo}}
style={{marginRight: 20, resizeMode: "contain", width: 70, height: 70, borderRadius: 50}}/>
<Text style={{color: Colors.white, fontSize: Sizes.h2}}>
Bem vindo, {RNStorage.userProfile.user.givenName}
</Text>
</View>
{items}
</ScrollView>
All inputs follow this structure:
Currently having this behavior (Not scrolling):
Expected Behavior
Scroll should work normally. I also tested using the ScrollView of the react-native-gesture-handler but it didn't work either.
This is unrelated to material-bottom-tabs.
You need to remove flex: 1 from contentContainerStyle. Otherwise your view will fill available scrollable area and won't be scrollable.

Responsive height of react-native-modal according to number of elements in it

i am trying to create a modal in react native application, and there is a button or touchable opacity on a screen which toggles the modal, i am trying to populate a list of items on modal by the use of mapping. But it is not working as expected because elements i create are hidden behind other elements.
I have tried using Modal from react native but i was unable to set custom size of the modal as i needed some portion of it to be transparent. That is why i moved to react-native-modal library but i am facing above mentioned error in that.
<Modal isVisible={this.state.modalVisible} >
<View style={{backgroundColor:'white', alignItems:'center', borderRadius:5}}>
<Image source={require('../../assets/Group3Copy.png')} style={{marginTop:responsiveFontSize, marginBottom:responsiveFontSize-2}}/>
<Text style={{color:'#92c848', alignSelf:'center', fontWeight:'bold', fontSize:responsiveFontSize+10}}>Well Done!</Text>
<Text style={{color:blueColor, fontWeight:'bold'}}>{this.state.plantCount} plants have been planted</Text>
<Text style={{color:blueColor, fontWeight:'bold'}}> {this.state.plantCount} پودے لگاۓ گۓ ہيں </Text>
{/* Mapping=========================================== */}
<View style={AppStyles.mainNoRow}>
<View style={AppStyles.colNoIco}>
<Image source={require('../../assets/plant.png')}/>
</View>
<View style={AppStyles.colOrderNoDetail}>
<Text style={{color:"#006f91", alignSelf:'flex-start', fontWeight:'bold',marginTop:10}}>Plant</Text>
<Text style={{color:"#747474", alignSelf:'flex-start', fontWeight:'bold',}}>Id</Text>
</View>
<View style={AppStyles.colOrderPickupYesDetail}>
<Text style={{color:greenColor ,fontWeight:'bold',}}>1 Jan 19</Text>
<Image source={require('../../assets/address.png')}/>
</View>
</View>
<TouchableOpacity onPress={this._toggleModal}
style={{
width: "90%",
height: 60,
justifyContent: "center",
alignSelf: "center",
borderWidth: 1,
borderRadius: 8,
borderColor: blueColor,
shadowColor: blueColor,
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.9,
shadowRadius: 1,
backgroundColor: blueColor,
marginBottom:responsiveFontSize}} >
<Text style={AppStyles.textStylePlant}>OK</Text>
</TouchableOpacity>
</View>
</Modal>
I expect it's height to be set according to the number of elements mapped on it. and adjust it automatically if that is possible.
But right now elements are overlapping like shown here in this picture. https://i.imgur.com/jH9sBxV.png
Elements are hidden behind 'OK' button.
Adding marginBottom to the styling of main row seems to resolve the issue. And it also resize the height of modal accordingly.

Setting the view height containing a scroll view with react native

I am trying to set a scroll view inside a view and setting a auto height to this view to full fit the parent content. Everything is wrapped inside a ImageBackground.
<ImageBackground source={{uri : 'url'}} style={{height: 350, width: null, flex: 1}}>
<View style={{flex: 1, height: 310}}>
<ScrollView contentContainerStyle={{flexGrow: 1}}>
<View style={{flex : 1}}>
<Text>
Simple text
</Text>
</View>
</ScrollView>
</View>
<ImageBackground/>
Actually, the height of the view is : height: 310 but it's supposed to be something like : height:'auto' to fill the whole parent content which is in my case the ImageBackground.
try this
width: '100%'
you can read the doc here
https://facebook.github.io/react-native/docs/dimensions

How to position a View at the bottom of a ScrollView?

I would like to create a screen with a ScrollView with some input fields in it, and a Button (actually 2 buttons in a normal View) at the bottom of the screen. This should be pretty easy, BUT, I want to position my button at the very bottom of the screen even if there isn't enough element in the ScrollView to fill the whole screen. I could use absolute positioning, BUT my ScrollView can be bigger (higher) then my screen, and in this case, the button should be at the end of the ScrollView. (So it would be out of the screen, which means the user should scoll down to see the button).
I've tried a lot of things, but the Button always comes right after the other elements inside the ScollView.
In the picture the scrollview has a blue border, and the normal view which contains the buttons has black border.
Any suggestion is appreciated.
Found the best solution.
The key is the contentContainerStyle property (doc: https://facebook.github.io/react-native/docs/scrollview#contentcontainerstyle). "These styles will be applied to the scroll view content container which wraps all of the child views. "
After setting flexGrow: 1, justifyContent: 'space-between', flexDirection: 'column' in contentContainerStyle, one can set justifyContent: 'flex-start' for the upper container view with the text, and justifyContent: 'flex-end' for the lower container view with the buttons.
<ScrollView
contentContainerStyle={{ flexGrow: 1, justifyContent: 'space-between', flexDirection: 'column' }}
style={{ backgroundColor: 'white', paddingBottom: 20 }}
>
<View style={{ flex: 1, justifyContent: 'flex-start' }}>
<Text>Some text with different length in different cases, or some input fileds.</Text>
</View>
<View style={{ flex: 1, justifyContent: 'flex-end' }}>
<View>
<TouchableOpacity style={[commonStyles.greenButton, styles.buttonPadding]}>
<Text style={commonStyles.greenButtonTitle}>Next</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity style={styles.cancelButtonContainer}>
<Text style={styles.cancelButton}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>;
<ScrollView
contentContainerStyle={{
flexGrow: 1,
justifyContent: 'flex-end',
}}>
</ScrollView>
I found a workaround for this.
The main idea is to set the height of the View with the texts and input fields to match exactly the height of the screen minus the View which contains the buttons.
The challenge is to calculate this height. Abhishek Kumar's answer helped me (https://stackoverflow.com/a/41398953/4109477) See my code below:
import { View, ScrollView, Text, TouchableOpacity, Dimensions } from 'react-native';
const screenHeight = Dimensions.get('window').height;
class MyClass extends React.Component {
constructor(props) {
super(props);
this.state = {buttonViewHeight: 0};
}
find_dimesions(layout){
this.setState({buttonViewHeight: layout.height});
}
render() {
return (
<View style={{minHeight: screenHeight, flex: 1, alignItems: 'center'}}>
<ScrollView style={{minHeight: screenHeight}}>
<View style={{minHeight: screenHeight}}>
<View style={{minHeight: screenHeight - this.state.buttonViewHeight, borderWidth: 2, borderColor: 'red', alignItems: 'center', flex: 1}]}>
<Text>Some text with different length in different cases, or some input fileds.</Text>
</View>
<View onLayout={(event) => { this.find_dimesions(event.nativeEvent.layout) }} style={{paddingBottom: 50, flex: 1, borderWidth: 2, borderColor: 'green'}}>
<TouchableOpacity
style={[commonStyles.greenButton, styles.buttonPadding]} >
<Text style={commonStyles.greenButtonTitle}>Next</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.cancelButtonContainer} >
<Text style={styles.cancelButton}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
</View>
}
}
On the picture below you can see the result
This solution will cause an animation like effect as the view renders multiple times, because of the changing of the View's height. The button's View "fade in" as you open the screen.
If you find a better solution please let me know!

How can you float: right in React Native?

I have an element that I want to float right, for example
<View style={{width: 300}}>
<Text style={{backgroundColor: "#DDD"}}>Hello</Text>
</View>
How can the Text be floated / aligned to the right? Also, why does the Text take up the full space of the View, instead of just the space for "Hello"?
why does the Text take up the full space of the View, instead of just the space for "Hello"?
Because the View is a flex container and by default has flexDirection: 'column' and alignItems: 'stretch', which means that its children should be stretched out to fill its width.
(Note, per the docs, that all components in React Native are display: 'flex' by default and that display: 'inline' does not exist at all. In this way, the default behaviour of a Text within a View in React Native differs from the default behaviour of span within a div on the web; in the latter case, the span would not fill the width of the div because a span is an inline element by default. There is no such concept in React Native.)
How can the Text be floated / aligned to the right?
The float property doesn't exist in React Native, but there are loads of options available to you (with slightly different behaviours) that will let you right-align your text. Here are the ones I can think of:
1. Use textAlign: 'right' on the Text element
<View>
<Text style={{textAlign: 'right'}}>Hello, World!</Text>
</View>
(This approach doesn't change the fact that the Text fills the entire width of the View; it just right-aligns the text within the Text.)
2. Use alignSelf: 'flex-end' on the Text
<View>
<Text style={{alignSelf: 'flex-end'}}>Hello, World!</Text>
</View>
This shrinks the Text element to the size required to hold its content and puts it at the end of the cross direction (the horizontal direction, by default) of the View.
3. Use alignItems: 'flex-end' on the View
<View style={{alignItems: 'flex-end'}}>
<Text>Hello, World!</Text>
</View>
This is equivalent to setting alignSelf: 'flex-end' on all the View's children.
4. Use flexDirection: 'row' and justifyContent: 'flex-end' on the View
<View style={{flexDirection: 'row', justifyContent: 'flex-end'}}>
<Text>Hello, World!</Text>
</View>
flexDirection: 'row' sets the main direction of layout to be horizontal instead of vertical; justifyContent is just like alignItems, but controls alignment in the main direction instead of the cross direction.
5. Use flexDirection: 'row' on the View and marginLeft: 'auto' on the Text
<View style={{flexDirection: 'row'}}>
<Text style={{marginLeft: 'auto'}}>Hello, World!</Text>
</View>
This approach is demonstrated, in the context of the web and real CSS, at https://stackoverflow.com/a/34063808/1709587.
6. Use position: 'absolute' and right: 0 on the Text:
<View>
<Text style={{position: 'absolute', right: 0}}>Hello, World!</Text>
</View>
Like in real CSS, this takes the Text "out of flow", meaning that its siblings will be able to overlap it and its vertical position will be at the top of the View by default (although you can explicitly set a distance from the top of the View using the top style property).
Naturally, which of these various approaches you want to use - and whether the choice between them even matters at all - will depend upon your precise circumstances.
You can directly specify the item's alignment, for example:
textright: {
alignSelf: 'flex-end',
},
For me setting alignItems to a parent did the trick, like:
var styles = StyleSheet.create({
container: {
alignItems: 'flex-end'
}
});
You are not supposed to use floats in React Native. React Native leverages the flexbox to handle all that stuff.
In your case, you will probably want the container to have an attribute
justifyContent: 'flex-end'
And about the text taking the whole space, again, you need to take a look at your container.
Here is a link to really great guide on flexbox: A Complete Guide to Flexbox
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'flex-end' }}>
<Text>
Some Text
</Text>
</View>
flexDirection: If you want to move horizontally (row) or vertically (column)
justifyContent: the direction you want to move.
Use flex: 1 and alignItems: 'flex-end' in View styling. Make sure to include flex: 1. That is the key to make the element float right
using flex
<View style={{ flexDirection: 'row',}}>
<Text style={{fontSize: 12, lineHeight: 30, color:'#9394B3' }}>left</Text>
<Text style={{ flex:1, fontSize: 16, lineHeight: 30, color:'#1D2359', textAlign:'right' }}>right</Text>
</View>
You can float:right in react native using flex:
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
for more detail: https://facebook.github.io/react-native/docs/flexbox.html#flex-direction
const styles = StyleSheet.create({
flowRight: {
flex:1,
justifyContent: 'end',
alignContent: 'end',
},
});
Then call styles.flowRight in your style
You can just style the text with alignSelf: 'flex-end':
<View style={{width: 300}}>
<Text style={{backgroundColor: "#DDD", alignSelf: 'flex-end'}}>Hello</Text>
</View>