Why are my buttons running off the screen? - react-native

I'm trying to have my two buttons sit in a row, equally spaced, and I want them of equal height and width. But they look like this at the moment.
I'm very new to React Native so please go gently!
Here's my code for what's returned.
return (
<View style={styles.screen}>
<View style={styles.horseProfile}>
<HorseProfile />
</View>
<View style={styles.vitalSignsGrid}>
<LargeVitalSigns />
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={this._alertHandler}>
<View style={styles.buttonStyling}>
<Text style={styles.buttonText}>ECG</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this._alertHandler}>
<View style={styles.buttonStyling}>
<Text style={styles.buttonText}>Resp Pattern</Text>
</View>
</TouchableOpacity>
</View>
<View>{/* timer and stop button */}</View>
</View>
)
Here are my styles.
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
horsePatientProfile: {
flex: 1
},
vitalSignsGrid: {
flex: 3,
backgroundColor: '#14172B'
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'green',
width: '100%',
flex: 4
},
buttonStyling: {
backgroundColor: '#2B4250',
borderRadius: 30,
alignItems: 'center',
justifyContent: 'space-around',
width: '50%',
height: '35%',
flexDirection: 'row',
},
buttonText: {
color: '#84C5C6',
fontWeight: 'bold'
}
})
Can anyone help please? Thank you.

the width of your buttons styles.buttonStyling is 50% which is 50% of the parent Component, the parent is the touchableOpacity, since it doesn't have a set width itself it will stretch with the content, in other words the 50% does not mean the same thing, you should give an exact (relative size, I like react-native-size-matter) to the touchable opacity and justifyContent as space between to space evenly

For height, width try using React Native Dimensions React Native Dimentions
Import it:
import {Dimensions} from "react-native";
var {height, width} = Dimensions.get('window');
Example using in style:
buttonStyling: {
backgroundColor: '#2B4250',
borderRadius: 30,
alignItems: 'center',
justifyContent: 'space-around',
width: width/2,
height: height / 3.5,
flexDirection: 'row',
},
or use Flexbox

Related

React Native: Vertically and Horizontally align image and text in same row

<View>
<Text>Hello</Text>
<Image source={require('./Vector.png')} />
</View>
I have the above View. I want to vertically and horizontally align image and text. Image should be on the right and text left in the same row. But I am not able to do align them correctly.
You can check here live dmeo here expo-snack:
Also the code is pretty ismple :
import * as React from 'react';
import { Text, View, StyleSheet,Image } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Hey</Text>
<Image source={{uri:'https://source.unsplash.com/random'}} style={{height:50,width:50}}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-between',
backgroundColor: '#ecf0f1',
padding: 8,
flexDirection:'row',
alignItems:'center'
}
});
hope it helps. feel free for doubts , and if you want the text and image to be not so distant you can have justifyContent: 'center',
For horizontal:
flexDirection: 'row',
For vertical:
flexDirection: 'column',
Use flexDirection: 'row' to make it in the same row & use justifyContent: 'center', alignItems: 'center' to align it vertically & horizontally.
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello</Text>
<Image style={{ width: 50, height: 50 }} source={require('./Vector.png')} />
</View>
You can simply do it by using flexDirection
Example :
<View
style={{
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<Text>Hello</Text>
<Image
style={{ width: 30, height: 30, resizeMode: "contain" }}
source={require("./Vector.png")}
/>
</View>
If you want to make the image right corner on the screen and text on the left corner try this. It can be done using position
<View
style={{
flex: 1,
flexDirection: "row"
}}
>
<Text style={{ position: "absolute", right: 0 }}>Hello</Text>
<Image
style={{
width: 30,
height: 30,
resizeMode: "contain",
position: "absolute",
left: 0
}}
source={require("./Vector.png")}
/>
</View>

Why does changing my margin percentage mess with the spacing of my custom buttons?

I'm new to React-Native and web development, but I do have a smidge of CSS experience. I've come across an issue that I can't figure out and I haven't found anything online that expresses a similar problem so that I may figure out why this is happening.
I have custom hexagonal buttons that I want to space out in a similar fashion to an onscreen keyboard which I have done, but my buttons are a bit too far up. The first row is obscured by the notification bar. My StyleSheet for my rows look like this:
const style = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#lele19'
},
firstRow: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
}
row: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
marginHorizontal: '5%'
}
});
Each "row" of buttons is within a View component.
So to try to fix the position so that the notification bar was not in the way I changed my paddingTop: from 5% to 15% and as a result, it seems to move my row down as I want, but now the space between my buttons is increased as seen from this screenshot:
It seems that any padding I do that is past 5% causes the spacing of my buttons to be off. How can I prevent this? What am I doing wrong? It appears this way on any device whether it is a phone or a tablet. Any help is greatly appreciated.
EDIT:
Since people are asking for more here is my PortraitLayout.js:
import React from 'react';
import { View, StyleSheet } from 'react-native';
import HexButton from './HexagonButton';
const PortraitLayout = props => {
return (
<View style={styles.screen}>
<View style={styles.firstRow}>
<HexButton>a</HexButton>
<HexButton>b</HexButton>
<HexButton>c</HexButton>
<HexButton>d</HexButton>
<HexButton>e</HexButton>
<HexButton>f</HexButton>
<HexButton>g</HexButton>
<HexButton>h</HexButton>
<HexButton>i</HexButton>
</View>
<View style={styles.row}>
<HexButton>j</HexButton>
<HexButton>k</HexButton>
<HexButton>l</HexButton>
<HexButton>m</HexButton>
<HexButton>n</HexButton>
<HexButton>o</HexButton>
<HexButton>p</HexButton>
<HexButton>q</HexButton>
<HexButton>r</HexButton>
</View>
<View style={styles.row}>
<HexButton>s</HexButton>
<HexButton>t</HexButton>
<HexButton>u</HexButton>
<HexButton>v</HexButton>
<HexButton>w</HexButton>
<HexButton>x</HexButton>
<HexButton>y</HexButton>
<HexButton>z</HexButton>
</View>
</View>
);
};
const styles = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#1e1e19'
},
firstRow: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
},
row: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
}
});
export default PortraitLayout;
HexagonButton.js:
import React from 'react';
import { View, StyleSheet, TouchableOpacity, Text, Dimensions } from 'react-native';
const HexagonButton = props => {
return (
<TouchableOpacity>
<View style={styles.hexagon}>
<View style={styles.hexagonInner}>
<Text style={styles.buttonText}>{props.children}</Text>
</View>
<View style={styles.hexagonBefore} />
<View style={styles.hexagonAfter} />
</View>
</TouchableOpacity>
);
};
let buttonWidth = Dimensions.get('window').width / 11; //Make enough room for 16 even though I am only putting 13 per row.
let buttonHeight = buttonWidth * 0.55;
const styles = StyleSheet.create({
hexagon: {
width: buttonWidth,
height: buttonHeight
},
hexagonInner: {
width: '100%',
height: '100%',
backgroundColor: '#ffec33',
justifyContent: 'center',
alignItems: 'center'
},
hexagonAfter: {
position: 'absolute',
bottom: -1 * (buttonHeight * 0.45),
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: buttonWidth * 0.5,
borderLeftColor: 'transparent',
borderRightWidth: buttonWidth * 0.5,
borderRightColor: 'transparent',
borderTopWidth: buttonHeight * 0.45,
borderTopColor: '#ffec33'
},
hexagonBefore: {
position: 'absolute',
top: -1 * (buttonHeight * 0.45),
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: buttonWidth * 0.5,
borderLeftColor: 'transparent',
borderRightWidth: buttonWidth * 0.5,
borderRightColor: 'transparent',
borderBottomWidth: buttonHeight * 0.45,
borderBottomColor: '#ffec23'
},
buttonText: {
fontSize: 18
}
});
export default HexagonButton;
and App.js:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import LandscapeLayout from './components/LandscapeLayout';
import PortraitLayout from './components/PortraitLayout';
export default function App() {
return (
<PortraitLayout/>
);
}
const styles = StyleSheet.create({
});
That is literally all of the code I have. I hope this will paint a better picture of the issue. I will try the borders thing and see what that yields.
EDIT:
Here is the result of the border color test. It looks like my buttons extend past the border. For simplicity, I only changed the top row so that the buttons were spaced incorrectly. Also for the sake of testing I added another style to the Portrait.js file that is just a copy of row.
I'm still not sure why it happens but I did manage to fix it. It had something to do with justifyContent and the fact that my button rows were not within a new of their own. I added a view around my button rows like this:
<View style={styles.screen}>
<View style={styles.keyboardLayout}>
<View style={styles.row}>
<HexButton>a</HexButton>
<HexButton>b</HexButton>
<HexButton>c</HexButton>
<HexButton>d</HexButton>
<HexButton>e</HexButton>
<HexButton>f</HexButton>
<HexButton>g</HexButton>
<HexButton>h</HexButton>
<HexButton>i</HexButton>
</View>
<View style={styles.row}>
<HexButton>j</HexButton>
<HexButton>k</HexButton>
<HexButton>l</HexButton>
<HexButton>m</HexButton>
<HexButton>n</HexButton>
<HexButton>o</HexButton>
<HexButton>p</HexButton>
<HexButton>q</HexButton>
<HexButton>r</HexButton>
</View>
<View style={styles.row}>
<HexButton>s</HexButton>
<HexButton>t</HexButton>
<HexButton>u</HexButton>
<HexButton>v</HexButton>
<HexButton>w</HexButton>
<HexButton>x</HexButton>
<HexButton>y</HexButton>
<HexButton>z</HexButton>
</View>
</View>
</View>
const styles = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#1e1e19'
},
row: {
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
},
keyboardLayout: {
height: '50%',
width: '100%',
alignItems: 'center',
justifyContent: 'flex-end'
}
});
I would still like to know the exact cause, but for now, my problem has been solved.

How to center react native headerTitle *component* (not string)

For the life of me, I can't center the headerTitle component. Ideas?
class GroupSelectionScreen extends React.Component{
static navigationOptions = ({navigation}) => {
return {
headerLeft: <View>
<Image source={logoImg} style={{width:72, height:33, marginLeft:5}}/>
</View>,
headerStyle: {
backgroundColor: theme.colors.darkBlue,
height: 75,
},
headerTitle: <View style={{
alignItems: "center",
flexDirection: 'row',
}}>
<View style={{backgroundColor: statusColor, width: 15, height: 15, borderRadius: 8}}></View>
<Text style={{color: 'white', fontSize: 25}}>{username}</Text>
</View>,
headerRight: <SetStatusButton onPress={navigation.getParam('toggleSetStatus')}/>,
};
};
Because you are using flexDirection:'row' you will probably want to add the property justifyContent:'center' to center the content of the view horizontally
This is due to the fact that justifyContent works on the primary axis and alignItems work on the secondary axis. Setting the flexDirection as row changes the primary axis to be row.
Adding flexDirection to a component's style determines the primary axis of its layout.
Adding justifyContent to a component's style determines the distribution of children along the primary axis.
You can see more in the docs
https://facebook.github.io/react-native/docs/flexbox
Here is a snack https://snack.expo.io/#andypandy/flexdirection
Each of the three views have flexDirection: 'row'
The first view has justifyContent: 'center' and the text is centred horizontally.
The second view has alignItems: 'center' and the text is centred vertically.
The third view has both justifyContent: 'center' and alignItems: 'center' and the text is centred horizontally and vertically
Here is an image of what it looks like
And here is the code
<View>
<View style={{flexDirection: 'row', justifyContent: 'center', backgroundColor: 'yellow', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', backgroundColor: 'cyan', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
<View style={{flexDirection: 'row', justifyContent: 'center', alignItems:'center', backgroundColor: 'forestgreen', height: 100, width: 100, margin: 10}} >
<Text>Hello</Text>
</View>
</View>
Update
In react-navigation there appears to be a difference between how headerTitle given by the question poster is handled in Android and iOS.
In iOS the headerTitle centres vertically and horizontally, however in Android it centres only vertically and is aligned left. Obviously this is not ideal.
There is a way to make it work in both iOS and Android, simply
Wrap the original header in a View with flex:1
Make sure the original header's View has a style with justifyContent: 'center' and alignItems: 'center'
Here is the code for the new headerTitle
<View style={{flex: 1}}>
<View style={{flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}>
<View style={{backgroundColor: 'green', width: 15, height: 15, borderRadius: 8}}/>
<Text>Spencer</Text>
</View>
</View>
Here is a snack showing it working https://snack.expo.io/#andypandy/navigation-header

React Native. How to place two Text with different fontSize in row with vertical align center

I need to align two Text component with different fontSize in a row and vertically centered. I have following now https://snack.expo.io/#troublediehard/dmVuZ2
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
row: {
flexDirection: 'row',
backgroundColor: 'red',
},
text1: {
fontSize: 20,
backgroundColor: 'blue',
},
text2: {
fontSize: 14,
backgroundColor: 'green',
},
});
For anyone that didn't found a solution yet, you have to wrap the text within another Text tag:
<View style={styles.container}>
<View style={styles.row}>
<Text>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</Text>
</View>
</View>
You need to add alignItems: 'center' to styles.row
row: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'red',
},

How to justify (left, right, center) each child independently?

In react native I have:
<View style={styles.navBar}>
<Text>{'<'}</Text>
<Text style={styles.navBarTitle}>
Fitness & Nutrition Tracking
</Text>
<Image source={icon} style={styles.icon}/>
</View>
with these styles:
{
navBar: {
height: 60,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
navBarTitle: {
textAlign: 'center',
},
icon: {
height: 60,
resizeMode: 'contain',
},
}
This is the effect I get:
This is the effect I want:
In the first example, the spacing between items is equal.
In the second example, each item is justified differently. The first item is left-justified. The second item is center-justified. The third, right-justified.
This question is similar, but it looks like react native does not support margin: 'auto'. Furthermore, the other answers only work if you only care about left and right justification, but no one really addresses center justification without auto margin.
I am trying to make a navigation bar in react native. The vanilla ios version looks like this:
(source: apple.com)
How do I do something similar? I'm mainly concerned with centering.
One way is to use nested View (flex containers) for 3 different regions and set flex:1 to left and right region
<View style={styles.navBar}>
<View style={styles.leftContainer}>
<Text style={[styles.text, {textAlign: 'left'}]}>
{'<'}
</Text>
</View>
<Text style={styles.text}>
Fitness & Nutrition Tracking
</Text>
<View style={styles.rightContainer}>
<View style={styles.rightIcon}/>
</View>
</View>
const styles = StyleSheet.create({
navBar: {
height: 60,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: 'blue',
},
leftContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
backgroundColor: 'green'
},
rightContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
backgroundColor: 'red',
},
rightIcon: {
height: 10,
width: 10,
resizeMode: 'contain',
backgroundColor: 'white',
}
});
You could also set marginLeft: 'auto' to the middle component. It should push it to the right. Also works for React Native
Source: https://hackernoon.com/flexbox-s-best-kept-secret-bd3d892826b6
If you're using a NavigationBar from the Navigator module see my question: Changing the default style for a Navigator.NavigationBar (title)
use this
marginLeft: "auto",
marginRight: "auto"