I am trying to have two large buttons (TouchableOpacity) be next to each other and take up 50% of the width of the screen.
But they only seem to be as wide as the Text component within them.
How can I make the two TouchableOpacity take up the full width of the screen, with each taking up 50% of the width?
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
backgroundColor: 'lightblue',
height: 200,
justifyContent: 'space-around',
},
btn: {
flex: 1,
backgroundColor: 'red',
justifyContent: 'center',
padding: 20,
borderWidth: 1,
},
});
return (
<View style={styles.container}>
<TouchableOpacity style={styles.btn}>
<Text>Left</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn}>
<Text>Right</Text>
</TouchableOpacity>
</View>
);
Try to add a width of 50% to your btn class
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
backgroundColor: 'lightblue',
height: 200,
justifyContent: 'space-around',
},
btn: {
width: '50%',
backgroundColor: 'red',
padding: 20,
borderWidth: 1,
},
});
You can also use dimensions from react native and put width: windowWidth/2 on your btn class.
A possible solution is to use react native's Dimensions
https://reactnative.dev/docs/dimensions
import { Dimensions } from 'react-native';
const width = Dimensions.get('window').width;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
backgroundColor: 'lightblue',
height: 200,
justifyContent: 'space-around',
},
btn: {
width: width*0.5,
backgroundColor: 'red',
padding: 20,
borderWidth: 1,
},
});
Related
I'm trying to change the background color and align the items on the center, so I tried this:
<View style={Stylesheet.container}>
<TouchableOpacity style={Stylesheet.button} onPress={() => navigation.navigate("Register")}>
Register
</TouchableOpacity>
<TouchableOpacity style={Stylesheet.button} onPress={() => navigation.navigate("Login")}>
Login
</TouchableOpacity>
</View>
The file with the styles is correct, I know that because it works on the TouchableOpacity and it is here:
import { StyleSheet } from 'react-native'
const Stylesheet = StyleSheet.create({
container: {
color: '#141414',
backgroundColor: '#141414',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
display: 'flex'
},
button: {
fontSize: '20px',
backgoundColor: 'white',
color: '#f63364',
alignItems: 'center',
justifyContent: 'center',
padding: '20px'
}
})
export default Stylesheet
But when I add the styling inline, it works fine
(...)
<View style={Stylesheet.container, { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#141414'}}>
(...)
How is that possible?
Give container flex value of 1:
const Stylesheet = StyleSheet.create({
container: {
flex:1,
color: '#141414',
backgroundColor: '#141414',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
},
button: {
fontSize: '20px',
backgoundColor: 'white',
color: '#f63364',
alignItems: 'center',
justifyContent: 'center',
padding: '20px'
}
})
I leave a small code of sample of as I have my code, in fact my code I show it inside a FlatList... but here I leave him something similar in .map that is practically the same thing, they are dynamic Views, I wish that on having clicked in the button, that View change Styles (Position Abosulte, Width, Backgorund color and more)
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
import AssetExample from './components/AssetExample';
let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles'];
export default function App() {
return (
<View style={styles.container}>
{shopping.map((data, idx) => {
return (
<View
style={{
width: '100%',
height: 70,
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
alignItems: 'center',
}}>
<Text>Tex: {data}</Text>
//I press this buttom, i want change this View Styles!!!, only this view
<TouchableOpacity onPress={() => {}}>
<View
style={{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
</View>
);
})}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
You can have a state variable and then set it to change the style.
<TouchableOpacity onPress={() => this.setState({changeStyleIndex:index})}>
<View
style={this.state.changeStyleIndex != index{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}:{change style goes here}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
import React from 'react'
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles'];
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
BackColor = '#f7f7f7',
StateWidth: '100%'
}
}
HandleChange = () => {
this.setState({
BackColor: 'red',
StateWidth: '50%'
})
}
render() {
const { BackColor, StateWidth } = this.state
return (
<View style={styles.container}>
{shopping.map((data, idx) => {
return (
<View
style={{
width: { StateWidth },
height: 70,
backgroundColor: { BackColor },
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
alignItems: 'center',
}}>
<Text>Tex: {data}</Text>
//I press this buttom, i want change this View Styles!!!, only this view
<TouchableOpacity onPress={() => { this.HandleChange }}>
<View
style={{
width: '100%',
height: 30,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f7f7',
marginTop: 5,
marginBottom: 5,
borderColor: '#dfdfdf',
borderWidth: 1,
borderRadius: 15,
}}>
<Text style={{ width: '100%' }}>Change</Text>
</View>
</TouchableOpacity>
</View>
);
})}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
I used the component by class, but change it to function and it will give crt, the logic is basically this.
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.
I am trying to style a NavBar for an app with a logo in the center and the back button on the left. I gotten pretty far in centering the logo and button horizontally. However, when I set a align-items:'center' attribute, it seems to break with Touchable Opacity. Is there a way I can center my components vertically and horizontally?
ex. |<- LOGO |
import React,{ Component } from 'react';
import { StyleSheet, View, Image, Text } from 'react-native';
import { colors } from '../../utils/theme';
import { widthScale, heightScale } from '../../utils/responsive';
import {TouchableOpacity}from 'react-native';
const logo = require('../../assets/images/logo.png');
const prev = require('../../assets/images/baseline-arrow_back-24px.png');
class NavBar extends Component{
constructor(props) {
super(props);
}
render(){
return(
<View style ={styles.nav}
<TouchableOpacity style= {styles.prev} onPress={handleClick()}>
<Image source={prev} />
</TouchableOpacity>
<Image style={styles.logo} source={logo} />
<Image source={prev} style={styles.tex} />
</View>
);
}
}
export default NavBar;
const styles = StyleSheet.create({
nav: {
flexDirection: 'row',
justifyContent: 'space-between',
backgroundColor: colors.tertiary,
width: widthScale('100%'),
height: heightScale('2%'),
paddingVertical: heightScale('4%'),
borderBottomWidth: 2,
borderWidth: 1,
flexWrap : 'wrap',
borderColor: 'green',
flex:1
},
logo: {
justifyContent: 'center',
alignItems:'center',
borderWidth: 1,
borderColor: 'blue'
},
info: {
justifyContent: 'center',
},
prev:{
borderRadius: 10,
borderWidth: 1,
borderColor: 'red',
alignItems:'center',
},
tex:{
borderRadius: 10,
borderWidth: 1,
borderColor: 'orange',
justifyContent: 'space-between',
alignItems:'center',
opacity: 0,
}
});
1. Without Touchable Buttons align-items: center, justify-content: center
2. With Touchable Buttons just justify-content: space-between
3. With Touchable Buttons justify-content: space-between and align-items: center
enter code here<SafeAreaView style={styles.maincontent}>
<View style={styles.toolbar}>
<TouchableOpacity style={{ justifyContent: 'center', }} activeOpacity={0.4} onPress={() => Actions.pop()}>
<Image source={{ uri: 'ic_arrow_back_gris_24dp' }} style={styles.back_img} />
</TouchableOpacity>
<Image source={{uri : 'logo'}} style={styles.back_txt}
/>
</View>
</SafeAreaView>
style :
maincontent: {
height: '100%',
width: '100%',
flexDirection: 'column',
backgroundColor: '#f1f1f1',
padding: 10
},
toolbar: {
backgroundColor: '#FFFFFF',
height: 50,
width: '100%',
flexDirection: 'row',
borderRadius: 3,
marginBottom: 10
},
back_img: {
height: 24,
width: 24,
justifyContent: 'center',
alignSelf: 'center',
marginLeft: 10,
padding: 4
},
back_txt: {
color: '#808080',
justifyContent: 'center',
alignSelf: 'center',
marginLeft: '13%',
fontSize: 14,
width: '65%'
},
It seems like the Touchable Opacity was stretching to fill space. By wrapping the Touchable Opacity in a View and limiting the width of that view, the styling worked as intended.
<View style={styles.nav}>
<View style={styles.toolbar}>
<TouchableOpacity style={{ justifyContent: 'nav'}} activeOpacity={0.4} onPress={this.props.prev}>
<Image source={prev} style={styles.back_img} />
</TouchableOpacity>
</View>
<Image source={logo} style={styles.back_txt}
/>
<Image source={prev} style={styles.tex} />
</View>
styles:
const styles = StyleSheet.create({
nav: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems:'center',
backgroundColor: colors.tertiary,
width: widthScale('100%'),
height: heightScale('2%'),
paddingVertical: heightScale('4%'),
borderBottomWidth: 2,
flexWrap : 'wrap',
},
tex:{
justifyContent: 'center',
alignItems:'center',
opacity: 0,
width: widthScale('10%')
},
toolbar: {
flexDirection: 'row',
alignItems: 'center',
width: widthScale('10%')
},
back_img: {
justifyContent: 'center',
alignSelf: 'center',
aspectRatio:1.5,
},
back_txt: {
justifyContent: 'center',
alignSelf: 'center',
},
});
I've been trying to add a shadow to an image and display it on an iOS device, but it just not showing up.
Any idea what I'm missing?
Here's the JSX:
<View style={styles.container}>
<Image style={styles.pic} source={pic} />
</View>
And the styles:
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
pic: {
width: 200,
height: 200,
shadowOffset: { width: 10, height: 10 },
shadowColor: 'black',
shadowOpacity: 1,
backgroundColor: '#0000',
},
});
You can view the live demo here.
According to React-native documentation : https://facebook.github.io/react-native/docs/image-style-props
There is no shadow possibilities for an Image style, thus you need to wrap it in a View and add a shadow to this view :
<View style={styles.mainContainer}>
<View style={styles.imageContainer}>
<Image style={styles.pic} source={pic} />
</View>
</View>
And style it like this :
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
},
imageContainer: {
shadowOffset: { width: 10, height: 10 },
shadowColor: 'black',
shadowOpacity: 1,
backgroundColor: '#0000',
},
pic: {
width: 150,
height: 150,
},
});