Im trying to get an image to fit within my view but it overshoots the view and covers most of the screen. I have tried other solutions I've found like resizeMode: "contain"/cover but none seem to fix it.
Heres my code:
return (
<View style={styles.container}>
<View style={styles.articlePicture}>
<Image source={require("../../assets/powerplant.jpg")} style={styles.image}></Image>
</View>
<View style={styles.contentContainer}>
<View style={styles.articleSubTitle}>
<Text>Travel</Text>
</View>
<View style={styles.articleTitle}>
<Text style={styles.title}>Lorem ipsum dolor sit amet</Text>
</View>
</View>
</View>
);
And here is my styles:
container: {
height: "100%",
width: "100%",
backgroundColor: "blue",
},
contentContainer: {
width: "100%",
height: "10%",
backgroundColor: "yellow",
},
articlePicture: {
height: "20%",
backgroundColor: "red",
},
articleTitle: {},
title: {
fontWeight: "bold",
},
articleSubTitle: {},
image: {
height: "100%",
flexDirection: "column",
flexWrap: "wrap",
aspectRatio: 1,
resizeMode: "contain",
},
Use CSS object-fit: cover;
I think something like bellow:
...
image: {
height: "100%",
flexDirection: "column",
flexWrap: "wrap",
aspectRatio: 1,
objectFit: "cover",
},
....
Related
I have a react native project where I want to orientate a element verticaly and center the text.
Now I want to use percentages so it is centered width wise which would be the height of the parent element. Also the text should wrap it gets to big.
The problem is I can not use percentage because it get always converted to px inside the browser.
Can someone help me out?
I appreciate your help.
The text on the left side should always be centered like it is in this screenshot. It behaves so weird, if the width is changing the text moves around.
type TeamsProps = {
name: string,
}
const TeamCard = (props: TeamsProps) => {
const [showOptions, setShowOptions] = useState<Boolean>(false)
const toggleOptions = () => {
setShowOptions(!showOptions)
}
return (
<View style={[styles.container, { height: (Dimensions.get("window").width - 3 * 15) / 2 }]}>
<TouchableOpacity onLongPress={toggleOptions} style={styles.card}>
<View style={styles.nameFlag}>
<Text style={styles.name}>{props.name}</Text>
</View>
<View style={styles.member}>
</View>
</TouchableOpacity>
{ showOptions ?
<TouchableOpacity onPress={toggleOptions} style={styles.options}>
<TextInput style={styles.input} value="Team Name"></TextInput>
<View style={styles.buttons}>
<TouchableOpacity style={[styles.button, styles.delete]}>
<Delete style={{ fontSize: 20, color: "white", margin: "auto" }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.confirm]}>
<Check style={{ fontSize: 20, color: "white", margin: "auto" }} />
</TouchableOpacity>
</View>
</TouchableOpacity>
: <></>
}
</View>
)
}
const styles = StyleSheet.create({
container: {
flexBasis: "calc(50% - 7.5px)"
},
card: {
backgroundColor: constants.mainColor,
borderRadius: 15,
shadowOpacity: 0.6,
shadowRadius: 10,
flex: 1,
flexDirection: "row",
alignItems: "center"
},
nameFlag: {
backgroundColor: constants.mainColorLight,
height: "calc(100% - 30px)",
width: "15%",
marginVertical: 15,
borderTopRightRadius: 30,
borderBottomRightRadius: 30,
justifyContent: "center"
},
name: {
position: "absolute",
// TODO: translateX needs to use -50%, translateY needs to use 50% of parent width
transform: [{ rotate: "-90deg" }, { translateX: -33 }, { translateY: 13 }],
transformOrigin: "left",
width: "max-content",
fontFamily: constants.fontFamilyHeader,
fontSize: constants.fontSizeHeader
},
member: {
backgroundColor: constants.mainColorLight,
height: "calc(100% - 30px)",
width: "calc(85% - 30px)",
margin: 15,
borderRadius: 30,
padding: 15,
flex: 1,
flexDirection: "row",
flexWrap: "wrap",
gap: 15,
justifyContent: "space-around",
alignItems: "center"
},
options: {
backgroundColor: constants.shadowColor,
position: "absolute",
top: 0,
left: 0,
zIndex: 100,
width: "100%",
height: "100%",
borderRadius: 15,
padding: 15,
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 25
},
input: {
backgroundColor: "white",
width: "100%",
borderRadius: 50,
padding: 5,
fontFamily: constants.fontFamilySubheader,
fontSize: constants.fontSizeHeader,
textAlign: "center"
},
buttons: {
flexDirection: "row",
gap: 25
},
button: {
borderRadius: 50,
width: 40,
height: 40
},
delete: {
backgroundColor: constants.alertColor
},
confirm: {
backgroundColor: constants.accentColor
}
})
Return to post
In my React Native app, I'm having trouble with making the children the same width as the parent. Please see image below:
I want the black and the green View to take the whole screen width, therefore get rid of the white background caused by the parent.
How can I achieve this? For example, I tried to apply width: 100% to the children, doesn't work. Several solutions like this, this and this don't work here.
Here is the code:
<View style={styles.containerWholePage}>
<View>
<View style={styles.upper}></View>
<View style={styles.lower}></View>
</View>
</View>
const styles = StyleSheet.create({
containerWholePage: {
alignItems: 'center',
},
lower: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'green',
flex: 6,
width: '100%', // doesn't work
},
upper: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'black',
flex: 3,
width: '100%', // doesn't work
},
});
Do you have an idea what I'm doing wrong?
This work for me as you want.
<View style={styles.containerWholePage}>
{/* <View> */}
<View style={styles.upper}></View>
<View style={styles.lower}></View>
{/* </View> */}
</View>
const styles = StyleSheet.create({
containerWholePage: {
alignItems: 'center',
flex:1,
},
lower: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'green',
// height:100,
flex: 6,
width: '100%', // doesn't work
},
upper: {
alignItems: 'center',
alignSelf: 'stretch',
backgroundColor: 'black',
flex: 3,
//height:200,
width: '100%', // doesn't work
},
});
I want to create a profile page where rounded image will be on top of two div in 30:70 ratio where top div will be empty and bottom div will contain few items. I have tried few code snippets from web.
<View style={{ flex: 1, flexDirection: 'column', backgroundColor: 'green', justifyContent: 'flex-start', alignItems: 'flex-start' }}>
<View style={{ flexDirection: 'column', justifyContent: "flex-start", alignItems: "flex-start", alignSelf: "flex-start" }}>
{/* <View style={{ flex: 1, flexDirection: 'row', alignItems: 'flex-end', alignSelf: 'flex-start', margin: 1 }}> */}
<View style={{ backgroundColor: 'white', borderRadius: 10, flexDirection: 'column', height: "30%", width: "100%" }}></View>
{/* </View> */}
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'flex-start', alignSelf: 'flex-start', margin: 1 }}>
<View style={{ backgroundColor: 'white', borderRadius: 10, flexDirection: 'column', height: "70%", width: "100%" }}></View>
</View>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center', alignSelf: 'center', position: 'absolute' }}>
<View style={{
backgroundColor: 'blue',
borderRadius: 10, height: 100, width: 100, borderRadius: 100 / 2
}}></View>
</View>
</View>
reference image
Taking as reference the image you share with us... You can have two views and set the profile avatar style to:
{
position: 'absolute',
alignSelf: 'center',
etc..
}
Check a quick demo: https://snack.expo.io/#abranhe/avatar-example
App.js
import React, { Component } from 'react';
import { Text, View, StyleSheet, ImageBackground, Image } from 'react-native';
import { Ionicons, FontAwesome } from '#expo/vector-icons';
import Constants from 'expo-constants';
import { avatar, background } from './data';
export default class App extends Component {
renderRow({ action, icon, fontAwesome = false }) {
return (
<View style={styles.actionRow}>
{fontAwesome
? <FontAwesome name={icon} size={25} />
: <Ionicons name={icon} size={32} />}
<Text style={styles.text}>{action}</Text>
</View>
);
}
render() {
return (
<View style={styles.container}>
<ImageBackground source={background} style={styles.background}>
<Image source={avatar} style={styles.avatar} />
</ImageBackground>
<View style={styles.content}>
{this.renderRow({ action: 'Scanner', icon: 'ios-camera' })}
{this.renderRow({
action: 'Profile',
icon: 'user-circle-o',
fontAwesome: true,
})}
</View>
</View>
);
}
}
You styles:
const styles = StyleSheet.create({
container: {
flex: 1,
},
background: {
width: '100%',
height: 130,
},
content: {
flex: 1,
marginTop: 80,
marginHorizontal: 10,
},
avatar: {
width: 100,
height: 100,
borderRadius: '50%',
borderWidth: 0.7,
borderColor: 'black',
position: 'absolute',
alignSelf: 'center',
marginTop: 80,
},
actionRow: {
width: '100%',
height: '50',
flexDirection: 'row',
alignItems: 'center',
margin: 10,
},
text: {
marginLeft: 15,
fontWeight: '500',
},
});
I'm trying to place my image over view that is already on other view but no success...
I had been trying to use position:'absolute' and more other options I had seen but it didn't work for me.
render() {
let locationFlag=Platform.OS === 'ios'?true:false
return (
<View style={styles.container}>
<LinearGradient
colors={[ '#75a4e7','#7d50f6']}
start={{x: .2, y: 1}}
end={{x:.8,y:0}}
locations={locationFlag?[.15,1]:[.18,2.1]}
style={styles.gradient}>
<View style={styles.profilePhotoContainer}>
<TouchableOpacity onPress={this.handleEditProfileImage.bind(this)}>
<Image
style={styles.profileImage}
source={this.state.profilePhoto}
/>
</TouchableOpacity>
</View>
</LinearGradient>
<View style={
[styles.profileBox]}
>
</View>
</View>
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignSelf: 'stretch',
backgroundColor: Colors.LIGHT_GRAY
},
gradient: {
alignSelf: 'stretch',
alignItems: 'center',
flexDirection: 'column',
height: Dimensions.get('window').height * .35,
},
profilePhotoContainer: {
zIndex: 50,
position: 'absolute',
backgroundColor:'blue',
top: Dimensions.get('window').height * .12,
elevation: 4,
},
profileImage: {
zIndex: 5,
width: 100,
height: 100,
borderRadius: 50,
borderWidth: 4,
borderColor: '#FFF',
backgroundColor: 'transparent',
},
profileBox: {
zIndex: 1,
position: 'absolute',
left: Dimensions.get('window').width * .07,
top: Dimensions.get('window').height * .18,
borderRadius: 8,
shadowRadius: 8,
elevation: 3,
shadowOpacity: 0.3,
backgroundColor: 'yellow',
width: Dimensions.get('window').width * .86,
height: Dimensions.get('window').height * .50,
}
In the link you can see what did I do so far and what is the issue:
https://imgur.com/a/kC4ZTUn
I want to achieve this situation:
https://imgur.com/a/KMSRVfZ
Thank you
You should take the View with the profilePhotoContainer style out from the LinearGradient view and then it will work perfectly!
Here is a sample code to achieve similar to the design,
<View style={{flex: 1}}>
<View style={{flex:0.33,backgroundColor:"aqua",justifyContent:"center",alignItems:"center"}}>
<View style={{position:"absolute",backgroundColor:"grey",height:200,width:100,borderRadius:5,left:0.23*width,top:0.25*height}}/> {/*Represents the box where you add user name, profession etc */}
<View style={{backgroundColor:"yellow",height:50,width:50,borderRadius:25}}/> {/*Image tag goes here */}
</View>
</View>
I don't feel the necessity to add position:"absolute" prop for the profilePhotoContainerthe positioning can be controlled by flex principles. You may require only one view with position:"absolute" prop.
Do comment if you require further assistance.
Get some help from this-
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity
} from 'react-native';
export default class Profile extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.header}></View>
<Image style={styles.avatar} source={{uri: 'https://bootdey.com/img/Content/avatar/avatar6.png'}}/>
<View style={styles.body}>
<View style={styles.bodyContent}>
<Text style={styles.name}>John Doe</Text>
<Text style={styles.info}>UX Designer / Mobile developer</Text>
<Text style={styles.description}>Lorem ipsum dolor sit amet, saepe sapientem eu nam. Qui ne assum electram expetendis, omittam deseruisse consequuntur ius an,</Text>
<TouchableOpacity style={styles.buttonContainer}>
<Text>Opcion 1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonContainer}>
<Text>Opcion 2</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
header:{
backgroundColor: "#00BFFF",
height:200,
},
avatar: {
width: 130,
height: 130,
borderRadius: 63,
borderWidth: 4,
borderColor: "white",
marginBottom:10,
alignSelf:'center',
position: 'absolute',
marginTop:130
},
name:{
fontSize:22,
color:"#FFFFFF",
fontWeight:'600',
},
body:{
marginTop:40,
},
bodyContent: {
flex: 1,
alignItems: 'center',
padding:30,
},
name:{
fontSize:28,
color: "#696969",
fontWeight: "600"
},
info:{
fontSize:16,
color: "#00BFFF",
marginTop:10
},
description:{
fontSize:16,
color: "#696969",
marginTop:10,
textAlign: 'center'
},
buttonContainer: {
marginTop:10,
height:45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
backgroundColor: "#00BFFF",
},
});
Lets assume that we have those react native styles:
var styles = StyleSheet.create({
parentView:{
width: 400,
height:150
},
containerView:{
flex:1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor:'black'
},
child1:{
backgroundColor: 'red',
alignSelf: 'flex-start'
},
child2: {
backgroundColor: 'yellow'
}
}
and that we have this render function:
render: function(){
return(
<View style={styles.parentView}>
<View style={styles.containerView}>
<Text style={styles.child1}>Child1</Text>
<Text style={styles.child2}>Child2</Text>
</View>
</View>
);
}
This code produces this image:
but what I want to achieve is this image:
VERY VERY IMPORTANT: I want child2 to be TOTALLY centered within the containerView, and not a bit far to the right because of the space that child1 occupies.
How can I achieve that in react-native?*
p.s.: Keep in mind that this will run on many resolutions (many screens with different aspect ratios) thus, it cannot be set in an absolute way that would result on it only working on "some" screens but not on others.
not sure if this is the best way to do it, but it works for me
render() {
return(
<View style={styles.parentView}>
<View style={styles.containerView}>
<View style={styles.rowContainer}>
<View style={styles.rowItem}>
<Text style={styles.child1}>Child1</Text>
</View>
<View style={styles.rowItem}>
<Text style={styles.child2}>Child2</Text>
</View>
</View>
</View>
</View>
);
const styles = StyleSheet.create({
parentView:{
width: 400,
height:150
},
containerView:{
flex:1,
flexDirection: 'row',
alignItems: 'center',
backgroundColor:'black'
},
rowContainer: {
flex: 1,
flexDirection: 'column',
},
rowItem:{
flex: 1
},
child1:{
backgroundColor: 'red',
position: 'absolute',
},
child2: {
alignSelf: 'center',
backgroundColor: 'yellow'
}
});