React Native: issue with flex layout - flexbox

I'm trying to make a simple view with 2 subviews - v1, v2 aligned horizontally and each taking 50% of the screen width.
To achieve this, I'm using the following code:
<View style={{flexDirection: 'row'}}>
<View style={{flex:1}}>
<View style={{flex:1}}>
</View>
I've also tried playing with other attributes- flexWrap, justifyContent.
However, everytime the views get stacked one after the other and doesn't take 50% of the screen. What am I doing wrong?
EDIT: The actual piece of code I'm using:
<View>
<Text style={styles.place}>New Delhi</Text>
<View style={{flexDirection: 'row'}}>
<DayTimeComponent style={{flex:1}}/>
<DayTimeComponent style={{flex:1}}/>
</View>
</View>

You can achieve this easily using react-native-easy-grid
Code:
import { Col, Row, Grid } from "react-native-easy-grid";
export default class StackOverflow extends Component {
render() {
return (
<View style={{flex:1}}>
<Grid>
<Col style={{backgroundColor:'yellow',alignItems:'center',justifyContent:'center'}}><Text>v1</Text></Col>
<Col style={{backgroundColor:'green',alignItems:'center',justifyContent:'center'}}><Text>v2</Text></Col>
</Grid>
</View>
);
}
}
Result:
You can also create custom layouts, for eg: if you need a 75%-25% split then all you need to do is
<Col size={75}></Col>
<Col size={25}></Col>

Set "flex:1" on both the container views. Like so:
<View style={{flex:1}}>
<Text style={styles.place}>New Delhi</Text>
<View style={{flexDirection: 'row', flex:1}}>
<DayTimeComponent style={{flex:1}}/>
<DayTimeComponent style={{flex:1}}/>
</View>
</View>

Related

How to use ScrollView with third party Components in React Native?

Very simple, how can I use ScrollView when using an third party (react-native-elements) List/List-Items? The given docs does not inform this: link
The list is fully working, but can't be scrolled:
Here is the code for rendering the list:
<View style={{ flex: 1 }}>
<List>
{
list.map((l, i) => (
<ListItem
roundAvatar
key={i}
title={l.name}
subtitle={
<View>
<View style={styles.subtitleView}>
<Text style={styles.ratingText}>{l.subtitle}</Text>
</View>
</View>
}
avatar={<Avatar
medium
rounded
source={l.avatar_url && { uri: l.avatar_url }}
title={l.name[0]}
/>}
/>
))
}
</List>
</View>
If I simply change the View to ScrollView, that should be the obvious move, I get this error:
I'm importing ScrollView from native-base and the List from react-native-elements.
Try to make the ScrollView under your View, also add additional View (not required) under the ScrollView.
<View style={{ flex: 1 }}>
<ScrollView>
<View>
<List>
{
list.map((l, i) => (
<ListItem
roundAvatar
key={i}
title={l.name}
subtitle={
<View>
<View style={styles.subtitleView}>
<Text style={styles.ratingText}>{l.subtitle}</Text>
</View>
</View>
}
avatar={<Avatar
medium
rounded
source={l.avatar_url && { uri: l.avatar_url }}
title={l.name[0]}
/>}
/>
))
}
</List>
</View>
</ScrollView>
</View>
Also consider using FlatList rather than ScrollView for better performance.
Reference:
https://facebook.github.io/react-native/docs/scrollview
https://facebook.github.io/react-native/docs/flatlist

ScrollView with flex 1 makes it un-scrollable

I'm trying to run flex on a ScrollView, and as long as the ScrollView has flex: 1 the scroll inside does not work.
here is the expo fiddle (that you can run this code and play with)
https://snack.expo.io/SySerKNp-
note that if you remove the flex: 1 from the ScrollView it does let scroll but then you lose the flex power ( the ability to let the red container down to push up the upper box (the ScrollView) ) so I must have a flex there.
p.s - I'm working only on android, and I haven't tested it on iPhone( I don't mind the result there )
any idea what am I missing ? why the ScrollView won't function right when it has a flex: 1 ?
thanks !
Try using flexGrow: 1 instead of flex: 1 in scrollView content container style as follows.
<ScrollView contentContainerStyle={{ flexGrow: 1, borderColor: 'green', borderWidth: 5 }}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box1} />
</ScrollView>
https://snack.expo.io/HkkEVoh6Z
I believe your problem is that you are telling the ScrollView to occupy all available space with flex=1 but the thing is that ScrollView works differently. It automatically renders all its children so it does work different with flex. That is the difference against a normal ListView or FlatList which have better performance.
I believe this snack solves that issue: https://snack.expo.io/SkxN9GOT-
Basically, I am getting the height of the device and setting the ScrollView with a fixed height, based on (screenHeight - the current height of the red box).
The best thing to do is to wrap your ScrollView in a View and control that view with flex, your scroll view will follow.
This is a little example
<View style={{flex: 1, flexDirection: 'column',}}>
<View style={{flex:5, backgroundColor : 'green' }}>
<ScrollView style={{margin:50, backgroundColor : 'pink' }}>
<Text> Hello Scroll View </Text>
<Text> Hello Scroll View </Text>
<Text> Hello Scroll View </Text>
<Text> Hello Scroll View </Text>
<Text> Hello Scroll View </Text>
<Text> Hello Scroll View </Text>
</ScrollView>
</View>
<View style={{flex:1, backgroundColor : 'blue' }}>
<Text> Hello Static View </Text>
</View>
</View>
This answer has already been provided how to do it.
But here's an explanation why you cannot do by your method. The styles given in contentContainerStyle is
applied to the scroll view content container which wraps all of the child views.
So when you apply flex: 1 to contentContainer it takes full height of ScrollView whose height is also flex: 1 as its parent View.
You can also simulate -
the ability to let the red container down to push up the upper box
by adding a parent to ScrollView and apply style in the parent
<View style={styles.root}>
<View style={{ flex: 1, borderColor: 'green', borderWidth: 5 }}>
<ScrollView>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box1} />
</ScrollView>
</View>
<View style={{ height: this.state.height, backgroundColor: 'red' }}>
<TouchableOpacity onPress={() => this.setState({ height: this.state.height + 10 })}>
<Text>Click</Text>
</TouchableOpacity>
</View>
</View>
Try this one it will 100% solve your problem
import React, { Component } from 'react';
import { AppRegistry, View,ScrollView } from 'react-native';
export default class AlignItemsBasics extends Component {
render() {
return (
// Try setting `alignItems` to 'flex-start'
// Try setting `justifyContent` to `flex-end`.
// Try setting `flexDirection` to `row`.
<View style={{ flex: 1,flexDirection: 'column' }}>
<View style={{ height: 50, backgroundColor: 'powderblue'}} />
<View style={{ flex: 1, backgroundColor: 'skyblue'}} >
<ScrollView>
<View style={{ flexDirection: 'column' , minHeight: 'fit-content'}} >
<View style={{ height:150, backgroundColor: 'red'}} />
<View style={{ minHeight: 'fit-content', backgroundColor: '#fe3222' }} />
<View style={{ height:150, backgroundColor: '#fff222'}} />
<View style={{ height:150, backgroundColor: '#555222'}} />
</View>
</ScrollView>
</View>
</View>
);
}
};
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);

How can I set my view to take top half of the screen for react-native android app?

I want to set my <View> to take only the top half of the screen. If I set flex:1 on the view's style, it will take the full screen. See below code:
render(){
return(
<View style={{flex:1}}>
...
</View>
);
}
I have tried to set the flex value to 0.5 but it doesn't help. How can I set my view takes half of the screen on flexbox?
render(){
return(
<View style={{flex:1}}>
<View style={{flex:.5}}>
...
</View>
<View style={{flex:.5}}/>
</View>
);
}
try this code:
<View style={{flex: 1,flexDirection:'row'}}>
<View style={{flex: 2, backgroundColor: 'powderblue',height:100}} />
<View style={{flex: 2, backgroundColor: 'skyblue',height:100}} />
</View>
Try this:
import {Dimensions, StyleSheet, View} from 'react-native';
const height = Dimensions.get('window').height*0.5;
const width = Dimensions.get('window').width;
const styles = StyleSheet.create({
container: {
width,
height
}
)};
render(){
return(
<View style={styles.container}>
...
</View>
);
}
Another way is you can use the Dimensions API to check the Height of the device and set the component height to half and position absolute: Dimensions

How to get the text from the Text Component within TouchableHighlight Component?

How can I get the text content from the Text Component within TouchableHighlight Component when clicked the TouchableHighlight component? Give me some idea to write the handleClickMenu function, thanks.
some code as following:
<View>
<TouchableHighlight underlayColor='#544b44' onPress={this.handleClickMenu}>
<View style={MenuListStyle.menuItem}>
<Icon name='heart' color='#df7454' style={MenuListStyle.menuItemIcon}/>
<Text style={MenuListStyle.menuItemText}>GODDESS</Text>
</View>
</TouchableHighlight>
<TouchableHighlight underlayColor='#544b44' onPress={this.handleClickMenu}>
<View style={MenuListStyle.menuItem}>
<Icon name='rss' color='#03a9f4' style={MenuListStyle.menuItemIcon}/>
<Text style={MenuListStyle.menuItemText}>BLOG</Text>
</View>
</TouchableHighlight>
...
</View>
You can use bind to pass additional argument. In this case MenuListStyle.menuItemText that you can get in handleClickMenu
handleClickMenu(text){
if(text === <something>){
//do something
}
}
render(){
...
<View>
<TouchableHighlight underlayColor='#544b44' onPress={this.handleClickMenu.bind(this, MenuListStyle.menuItemText)}>
<View style={MenuListStyle.menuItem}>
<Icon name='heart' color='#df7454' style={MenuListStyle.menuItemIcon}/>
<Text style={MenuListStyle.menuItemText}>GODDESS</Text>
</View>
</TouchableHighlight>
<TouchableHighlight underlayColor='#544b44' onPress={this.handleClickMenu.bind(this, MenuListStyle.menuItemText)}>
<View style={MenuListStyle.menuItem}>
<Icon name='rss' color='#03a9f4' style={MenuListStyle.menuItemIcon}/>
<Text style={MenuListStyle.menuItemText}>BLOG</Text>
</View>
</TouchableHighlight>
...
</View>
}

Style part of a text component

I am trying to make react native components where different words in the same component have different styling.
For example I have buttons with name and subtitle on the button, I want the subtitle text to be smaller.
<Text style={styles.buttonText}>{speciesArry[i].title} {"\n"} {speciesArry[i].subtitle}</Text>
I need to wrap the subtitle in its own component so that I can style it?
A second example
I have another button with the text component
Green - best Choice
I need the the word "green" to be green.
For the first question, a button with a title and a subtitle, you can wrap a view in a TouchableHighlight and then place multiple Text elements to create a title and a subtitle:
<TouchableHighlight style={{height:70, backgroundColor: 'blue'}}>
<View style={{flexDirection: 'column', }}>
<Text style={{textAlign:'center', color: 'white', fontSize:22, marginTop:10}}>MAIN TEXT</Text>
<Text style={{textAlign:'center', color: 'white', fontSize:14}}>Subtitle</Text>
</View>
</TouchableHighlight>
For the second question, having different styling within a single text component, you need to wrap text components within text components, the way you might do with a span in html:
<Text style={styles.mainStyle}>This text is red, <Text style={styles.blacktext}>this text is black, </Text><Text style={styles.boldgreen}>this text is bold and green!</Text></Text>
And the button example you provided above would look something like this:
<TouchableHighlight style={{height:70, backgroundColor: 'orange'}}>
<View style={{ flexDirection: 'row', justifyContent:'center'}}>
<Text style={{fontSize:18, marginTop: 22}}><Text style={{color: 'green'}}>Green</Text> - best Choice</Text>
</View>
</TouchableHighlight>
For the float:right question: There is no anything exactly like it in flexbox, but there is something very similar to it called: justifyContent: 'flex-end'. Below is how that would look, and I've updated the origin project to reflect the below code:
<View style={{flexDirection: 'row', justifyContent: 'flex-end'}}>
<Text>Floating right</Text>
</View>
I've set up a full working project with the above examples here, and pasted the entire code for the project below as well. Hope this helps!
https://rnplay.org/apps/KqE-cA
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight,
} = React;
var SampleApp = React.createClass({
render: function() {
return (
<View style={styles.container}>
<View style={{marginTop:70}}>
<TouchableHighlight style={{height:70, backgroundColor: 'blue'}}>
<View style={{flexDirection: 'column', }}>
<Text style={{textAlign:'center', color: 'white', fontSize:22, marginTop:10}}>MAIN TEXT</Text>
<Text style={{textAlign:'center', color: 'white', fontSize:14}}>Subtitle</Text>
</View>
</TouchableHighlight>
</View>
<View style={{marginTop:20}}>
<Text style={styles.mainStyle}>This text is red, <Text style={styles.blacktext}>this text is black, </Text><Text style={styles.boldgreen}>this text is bold and green!</Text></Text>
</View>
<View style={{marginTop:20}}>
<TouchableHighlight style={{height:70, backgroundColor: 'orange'}}>
<View style={{ flexDirection: 'row', justifyContent:'center'}}>
<Text style={{fontSize:18, marginTop: 22}}><Text style={{color: 'green'}}>Green</Text> - best Choice</Text>
</View>
</TouchableHighlight>
</View>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
},
mainStyle: {
color: 'red'
},
blacktext: {
color: 'black'
},
boldgreen: {
color: 'green',
fontWeight: 'bold'
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);

Resources