React Native flex and custom component layout issue - react-native

I've a simple React Native component:
export default class TestComponent extends React.Component {
render() {
return (
<View style={{flex:1}}>
<Text>Test</Text>
</View>
);
}
}
It is used by this App:
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={{ flex: 0, backgroundColor: 'red' }}>
<TestComponent />
</View>
<View style={{ flex: 0, backgroundColor: 'yellow' }}>
<Text>2</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 10,
},
});
I expect the TestComponent and the yellow view to be displayed but using only required space and the blue view to fill up the remaining content.
The yellow and blue area is working as expected, but the TestComponent is not displayed. Why?
See this demo: https://snack.expo.io/#dennismadsen/great-fudge

just don't use flex:0
use flex:1 in component that you want to fill the remain screen
the 2 others don't write any flex
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={{ backgroundColor: 'red' }}>
<TestComponent />
</View>
<View style={{ backgroundColor: 'yellow' }}>
<Text>2</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 10,
},
});

Just remove flex: 0 from your JSX and it will work.
render() {
return (
<View style={styles.container}>
<View style={{ backgroundColor: 'red' }}>
<TestComponent />
</View>
<View style={{ backgroundColor: 'yellow' }}>
<Text>2</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
}
Reason:
When you want only 1 component to cover the rest area then you just need to give the element flex: 1 and leave others as is, so that they can only take the required space. When you explicitly assign flex: 0 then it won't even take the required space.
FYI, I already tried this in the demo link you have shared.
EDITED:
export default class TestComponent extends React.Component {
render() {
return (
<Text>Test</Text>
);
}
}
OR
export default class TestComponent extends React.Component {
render() {
return (
<View>
<Text>Test</Text>
</View>
);
}
}

You need to just remove flex:1 from <Testcomponent/> then you test component take size according to its content.
Please check this demo link
https://snack.expo.io/#vishal7008/new-component
Working demo image

The reason why 'TestComponent' is not visible is because the parent flex value is zero. The flex will be covered together in yellow with zero.
You have to set flex values to see all colors and letters.
red: 1 yellow : 1 blue : 8 === 1:1:8 === 0.1 : 0.1 : 0.8
return (
<View style={styles.container}>
<View style={{ flex: 1, backgroundColor: 'red' }}>
<TestComponent />
</View>
<View style={{ flex: 1, backgroundColor: 'yellow' }}>
<Text>2</Text>
</View>
<View style={{ flex: 8, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
You can use two things if you want to make the text equal to the height of the second view. You can use flexBasis or height
'flexBasis' and 'height' do the same thing.
OR
You can also use flexShrink.
// use `flexBasis` or `height`
return (
<View style={styles.container}>
<View style={{ backgroundColor: 'red',flexBasis: 20 }}>
<TestComponent />
</View>
<View style={{backgroundColor: 'green',height: 20 }}>
<Text>2</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
use `flexShrink`.
return (
<View style={styles.container}>
<View style={{ backgroundColor: 'red',flexBasis: 20 }}>
<TestComponent />
</View>
<View style={{backgroundColor: 'green',flexShrink:0 }}>
<Text>2</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
);
Remove Flex value
<View style={styles.container}>
<View style={{ backgroundColor: 'red'}}>
<TestComponent />
</View>
<View style={{backgroundColor: 'green'}}>
<Text>222222222222222222</Text>
<Text>111111111111111111</Text>
<Text>535555555555</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue' }}>
<Text>3</Text>
</View>
</View>
....
<View>
<Text>Test</Text>
<Text>Test</Text>
<Text>Test</Text>
</View>
See Screen

Related

react native text horizontal cutting, need full text in one line how to do that?

react-native version: "0.62.0", I tried this code
ui coming like this:
React Native
</View>
<View style={{flex:8}}>
<View style={{padding: 20, height: 200, backgroundColor: 'red'}}>
<Text style={fonts.bold}>View 1</Text>
</View>
<View style={{padding: 20, height: 200, backgroundColor: 'red'}}>
<Text style={fonts.bold}>View 1</Text>
</View>
<View style={{padding: 20, height: 200, backgroundColor: 'yellow'}}>
<Text>View 1</Text>
</View>
<View style={{padding: 20, height: 200, backgroundColor: 'green'}}>
<Text>View 1</Text>
</View>
</View>
</View>
How to do it?
give Text width greater than space occupied by characters with some padding
It looks like you did not provide the code for intended green view. The green view in your code is different. It is under yellow view.
Tip: For intended view try to remove height and width properties.
Created a sample according to your problem
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<View style={styles.wrapperStyle}>
<View style={styles.leftStyle}>
<Text style={styles.textStyle}>Trending</Text>
</View>
<View style={styles.rightStyle}>
<Text>View 1</Text>
</View>
</View>
<View style={styles.wrapperStyle}>
<View style={[styles.leftStyle, { backgroundColor: 'green' }]}>
<Text style={styles.textStyle}>Top_games</Text>
</View>
<View style={[styles.rightStyle, { backgroundColor: 'yellow' }]}>
<Text>View 2</Text>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: 20,
},
wrapperStyle: {
height: 200,
flexDirection: 'row'
},
leftStyle: {
flex: 2,
backgroundColor: 'gray',
alignItems: 'center',
justifyContent: 'center'
},
rightStyle: {
flex: 8,
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center'
},
textStyle: {
transform: [{ rotate: '-90deg' }]
}
});
Somtetimes you have to change flex value according to your requirements.
Hope this helps you. Feel free for doubts.

ImageBackground not showing image on some devices

I am trying to use a CustomCallout with a ImageBackground in it. I notice a really strange behavior when testing the application on two different devices (both Android). The image is showed correctly on the older device with lower display, but on the new device (p30 lite) the image is not appearing.. any ideas? here is my code:
class CustomCallout extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.calloutStyle}>
<View>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<ImageBackground
source={{ uri: this.props.image }}
style={styles.bgImage}
>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={1}>
{this.props.placeName}
</Text>
</View>
</ImageBackground>
</View>
<View style={{ ...styles.placeRow, ...styles.placeDetail }}>
<Text>{this.props.distance}m</Text>
<Text>{this.getPlaceType(this.props.placeType)}</Text>
</View>
<View style={{ ...styles.placeRow, ...styles.placeRating }}>
<StarRating
disabled={false}
emptyStar={'ios-star-outline'}
fullStar={'ios-star'}
halfStar={'ios-star-half'}
iconSet={'Ionicons'}
maxStars={7}
rating={4}
fullStarColor={'#FDCC0D'}
starSize={20}
/>
</View>
</View>
</View>
);
}
}
CustomCallout.propTypes = propTypes;
const styles = StyleSheet.create({
calloutStyle: {
height: 200,
width: 280,
backgroundColor: '#61adc8',
shadowOffset: { width: 0, height: 2},
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 55,
padding: 12,
borderRadius: 20,
shadowColor: 'black',
overflow: 'hidden'
},
bgImage: {
width: '100%',
height: '100%',
justifyContent: 'flex-end',
},
placeRow: {
flexDirection: 'row'
},
placeHeader: {
height: '80%'
},
placeDetail: {
justifyContent: 'space-between',
height: '10%'
},
placeRating: {
height: '10%',
justifyContent:'flex-start',
},
titleContainer: {
backgroundColor: 'rgba(0,0,0,0.5)',
shadowOffset: { width: 0, height: 2},
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 55,
borderRadius: 10,
alignItems: 'center'
},
title: {
color: 'white',
fontSize: 20
}
});
export default CustomCallout;
We cant put ImageBackground wherever we want.. I don't know the exact theory. But Just put the ImageBackgroung tag outside the view and try to even put on different views too.. If anyone know plz correct me. Here is a working example.
Put ImageBackground to entire component
render() {
return (
<View style={styles.calloutStyle}>
<View>
<ImageBackground
source={{ uri: 'https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg' }}
style={styles.bgImage}
>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={1}>
{this.props.placeName}
</Text>
</View>
</View>
</ImageBackground>
<View style={{ ...styles.placeRow, ...styles.placeDetail }}>
<Text>{this.props.distance}m</Text>
<Text>{this.getPlaceType(this.props.placeType)}</Text>
</View>
<View style={{ ...styles.placeRow, ...styles.placeRating }}>
<StarRating
disabled={false}
emptyStar={'ios-star-outline'}
fullStar={'ios-star'}
halfStar={'ios-star-half'}
iconSet={'Ionicons'}
maxStars={7}
rating={4}
fullStarColor={'#FDCC0D'}
starSize={20}
/>
</View>
</View>
</View>
);
}
}
Or you can put to only both components
render() {
return (
<View style={styles.calloutStyle}>
<View>
<ImageBackground
source={{ uri: 'https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg' }}
style={styles.bgImage}
>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={1}>
{this.props.placeName}
</Text>
</View>
</View>
<View style={{ ...styles.placeRow, ...styles.placeDetail }}>
<Text>{this.props.distance}m</Text>
<Text>{this.getPlaceType(this.props.placeType)}</Text>
</View>
<View style={{ ...styles.placeRow, ...styles.placeRating }}>
<StarRating
disabled={false}
emptyStar={'ios-star-outline'}
fullStar={'ios-star'}
halfStar={'ios-star-half'}
iconSet={'Ionicons'}
maxStars={7}
rating={4}
fullStarColor={'#FDCC0D'}
starSize={20}
/>
</View>
</ImageBackground>
</View>
</View>
);
}
}
or put ImageBackground to inside view only
render() {
return (
<View style={styles.calloutStyle}>
<View>
<ImageBackground
source={{ uri: 'https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg' }}
style={styles.bgImage}
>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={1}>
{this.props.placeName}
</Text>
</View>
</View>
</ImageBackground>
<View style={{ ...styles.placeRow, ...styles.placeDetail }}>
<Text>{this.props.distance}m</Text>
<Text>{this.getPlaceType(this.props.placeType)}</Text>
</View>
<View style={{ ...styles.placeRow, ...styles.placeRating }}>
<StarRating
disabled={false}
emptyStar={'ios-star-outline'}
fullStar={'ios-star'}
halfStar={'ios-star-half'}
iconSet={'Ionicons'}
maxStars={7}
rating={4}
fullStarColor={'#FDCC0D'}
starSize={20}
/>
</View>
</View>
</View>
);
}
}
Try this out and let me know the result.. :)

how to wrap text inside the screen?

hi there i have a small problem i dont know why my text dont want to be wrapped but the problem the same code work for me in other screen but in the screen below dont want to work ?
here is some screenshot from my phone
image 1
image 2
and this is my code
import React from 'react';
import { View, Text } from 'react-native';
const Part = (props) => (
<View style={{ flexDirection: 'row', marginHorizontal: 20, marginVertical: 10 }}>
<Text style={{ marginHorizontal: 10 }}>-</Text>
<View>
<Text style={{ flexWrap: 'wrap' }}>{props.name}</Text>
{props.adress !== null ? <View style={{ flexDirection: 'row' }}>
<Text>Adresse : </Text>
<View style={{ flexDirection: 'row' }} >
<Text style={{ flexWrap: 'wrap' }}>{props.adress}</Text>
</View>
</View> : null }
{props.tel !== null ? <View style={{ flexDirection: 'row' }}>
<Text>Tél : </Text>
<View>
{props.tel.map((tel) => (
<Text>{tel}</Text>
)
) }
</View>
</View> : null }
{props.fax !== null ? <View style={{ flexDirection: 'row' }}>
<Text>Fax : </Text>
<View>
{props.fax.map((fax) => (<Text>{fax}</Text>))}
</View>
</View> : null}
</View>
</View>
);
export default Part;
give width in percentage Like
<View style={{ flexDirection: 'row'' }}>
<Text>Adresse : </Text>
<View style={{ flexDirection: 'row',width:'50% }} >
<Text style={{ flexWrap: 'wrap' }}>{props.adress}</Text>
</View>

How to set arrow icon center to the screen end in list item in react native

I am new to react native, In my application I have list. So that i have taken flatlist. I have designed the list item. But arrow icon need to set end of the item. I have tried many ways how to do this.
This is the my code
<View style={styles.MainContainer}>
<FlatList
data={ this.state.FlatListItems }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={
({item}) =>
<View style={styles.main}>
<View style={styles.itemContainer}>
<View>
<Image source={require('./resource/ic_drawer.png')} />
<Text style={styles.item} onPress={this.GetItem.bind(this, item.key)} >
{item.key}
</Text>
</View>
<View style={styles.balanceItem}>
<View>
<Text >Balance</Text>
<Text >$89.04</Text>
</View>
<View style={styles.subItem}>
<View>
<Text >Account number</Text>
<Text >743509-001</Text>
</View>
<View style={styles.balanceItem}>
<Text >Meter number</Text>
<Text >17976849</Text>
</View>
</View>
</View>
<View style={styles.balanceItem}>
<View style={styles.duenbuttonItem}>
<View>
<Text >Due Date</Text>
<Text >30/09/2016</Text>
</View>
</View>
<TouchableOpacity style={styles.btn} onPress={this.login}><Text style={{color: 'white'}}>PAY NOW</Text></TouchableOpacity>
</View>
</View>
<Image source={require('./resource/arrow_24.png')} style={styles.arrowImage}/>
</View>
}
/>
</View>
and this is my styles
const styles = StyleSheet.create({
MainContainer :{
// Setting up View inside content in Vertically center.
justifyContent: 'center',
flex:1,
margin: 10
},
item: {
padding: 0,
fontSize: 18,
},
itemContainer :{
flex: 1,
flexDirection: 'row',
padding : 10,
},
subItem: {
marginTop: 10,
flexDirection: 'row',
},
btn:{
borderRadius: 10,
alignSelf: 'stretch',
backgroundColor: '#003366',
padding: 10,
marginTop: 10,
alignItems: 'center',
},
balanceItem: {
marginLeft: 5,
},
duenbuttonItem: {
marginLeft: 10,
flexDirection: 'row',
},
arrowImage: {
justifyContent: 'flex-end',
justifyContent: 'center',
},
main:{
flex: 1,
}
});
And this the output of the above code
Here my requirement is the arrow image end of the item in center. So please guide me how to do this?

Layout arrangement in React Native

I'm trying to work on this Instagram layout using React Native:
However, I'm unable to arrange the layout properly. Here is my code:
import React from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import StatusBarBackground from './StatusBarBackground';
export default class App extends React.Component {
render() {
return (
<View>
<StatusBarBackground />
<View style={styles.user_profile}>
<View style={styles.container}>
<Image style={styles.image} source={require('./images/user_profile.jpg')}/>
</View>
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={styles.container}>
<Text style={styles.numbers}>128</Text>
<Text style={styles.grey_text}>posts</Text>
</View>
<View style={styles.container}>
<Text style={styles.numbers}>256</Text>
<Text style={styles.grey_text}>followers</Text>
</View>
<View style={styles.container}>
<Text style={styles.numbers}>184</Text>
<Text style={styles.grey_text}>following</Text>
</View>
</View>
<View style={styles.btnContainer}>
<Button title="Edit Profile" color="#000" backgroundColor="#CCC" raised={true} onPress={this.onPressEditProfile} />
</View>
</View>
</View>
);
}
onPressEditProfile(event) {
console.log('Clicked Edit Profile');
}
}
const styles = StyleSheet.create({
user_profile: {
width: '100%',
height: 120,
alignItems: 'flex-start',
flexDirection: 'row',
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
image: {
height: 100,
borderRadius: 50,
width: 100,
margin: 10,
alignItems: 'center',
justifyContent: 'center',
},
grey_text: {
color: '#999',
},
numbers: {
fontWeight: 'bold',
},
btnContainer: {
backgroundColor: '#CCC',
borderRadius: 10,
padding: 10,
},
});
It looks like this now:
What did I miss in the layout?
You just applied flexDirection: 'row' to common container so it was cause of your result layout.
I've provided some pseudocode just for your understanding.
const style = StyleSheet.create({
container: {},
infoTopRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
infoBottomRow: {
justifyContent: 'center',
alignItems: 'center',
},
});
<View style={...}>
<Avatar/>
<View style={...}> {/* <---- here should be flexDirection: 'column' or just don't set any value for it */}
<View style={style.infoTopRow}>
<InfoBlock title="posts" value="128" />
<InfoBlock title="followers" value="256" />
<InfoBlock title="following" value="184" />
</View>
<View>
<Button title="Edit Profile" />
</View>
</View>
</View>
You are missing one more wrapper column view
<View>
<StatusBarBackground />
<View style={styles.user_profile}>
//Make this container something like flex:0.2
<View style={styles.container}>
<Image style={styles.image} source={require('./images/user_profile.jpg')}/>
</View>
// You need another column view wrapper
<View style={{flex:0.8}}>
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={styles.container}>
<Text style={styles.numbers}>128</Text>
<Text style={styles.grey_text}>posts</Text>
</View>
<View style={styles.container}>
<Text style={styles.numbers}>256</Text>
<Text style={styles.grey_text}>followers</Text>
</View>
<View style={styles.container}>
<Text style={styles.numbers}>184</Text>
<Text style={styles.grey_text}>following</Text>
</View>
</View>
<View style={styles.btnContainer}>
<Button title="Edit Profile" color="#000" backgroundColor="#CCC" raised={true} onPress={this.onPressEditProfile} />
</View>
</View>
</View>
</View>