'React-Native Image Height (Full Width)
I have an image that I pull down from a url. I do not know the dimensions of this image ahead of time.
How do I style / layout the <Image/>
so it is the full width of the parent view and the height is calculated so that the aspect ratio is maintained?
I have tried using onLoad
in 0.34.0-rc.0 and the height / width are both 0 in event.nativeEvent.source
.
The image is in a <ScrollView/>
. I am not after a full screen image.
Solution 1:[1]
React Native has a function built in that will return the width and height of an image: Image.getSize()
. Check out the documentation here
Solution 2:[2]
My use was very similar in that I needed to display an image with full screen width but maintaining its aspect ratio.
Based on @JasonGaare's answer to use Image.getSize()
, I came up with the following implementation:
class PostItem extends React.Component {
state = {
imgWidth: 0,
imgHeight: 0,
}
componentDidMount() {
Image.getSize(this.props.imageUrl, (width, height) => {
// calculate image width and height
const screenWidth = Dimensions.get('window').width
const scaleFactor = width / screenWidth
const imageHeight = height / scaleFactor
this.setState({imgWidth: screenWidth, imgHeight: imageHeight})
})
}
render() {
const {imgWidth, imgHeight} = this.state
return (
<View>
<Image
style={{width: imgWidth, height: imgHeight}}
source={{uri: this.props.imageUrl}}
/>
<Text style={styles.title}>
{this.props.description}
</Text>
</View>
)
}
}
Solution 3:[3]
I am new on react-native but I came across this solution using a simple style:
imageStyle: {
height: 300,
flex: 1,
width: null}
Image full width from my 1º App:
It worked for me.
Solution 4:[4]
It worked for me.
import React from 'react'
import { View, Text, Image } from 'react-native'
class Test extends React.Component {
render() {
return (
<View>
<Image
source={{ uri: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQL6goeE1IdiDqIUXUzhzeijVV90TDQpigOkiJGhzaJRbdecSEf" }}
style={{ height: 200, left: 0, right: 0 }}
resizeMode="contain"
/>
<Text style={{ textAlign: "center" }}>Papaya</Text>
</View>
);
}
}
export default Test;
Another way you can get width of parent view after layout event.
<View
style={{ flex: 1}}
layout={(event) => { this.setState({ width: event.nativeEvent.layout.width }); }}
/>
When you get width parent view from layout event then you can assign width to Image tag.
import React from 'react';
import { View, Image } from 'react-native';
class Card extends React.Component {
constructor(props) {
super(props);
this.state = {
height: 300,
width: 0
};
}
render() {
return (
<View style={{
flex: 1,
flexDirection: 'row'
}}>
<View style={{ width: 50, backgroundColor: '#f00' }} />
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fafafa' }}
onLayout={(event) => { this.setState({ width: event.nativeEvent.layout.width }); }}
>
{
this.state.width === 0 ? null : (
<Image
source={{ uri: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQL6goeE1IdiDqIUXUzhzeijVV90TDQpigOkiJGhzaJRbdecSEf" }}
style={{ width: this.state.width, height: this.state.height }}
resizeMode="contain"
/>
)
}
</View>
</View>
);
}
}
export default Card;
Solution 5:[5]
if you have a static image you can use like this
import React, { Component } from "react";
import { View, Animated, Image, Dimensions } from "react-native";
import splashScreen from "../../../assets/imgs/splash-screen.png";
export default class MasterPage extends Component {
constructor(props) {
super(props);
this.state = {
fadeAnim: new Animated.Value(0),
imgWidth: 0,
imgHeight: 0
};
}
checkLogIn = async () => {
const width = 533; // set your local image with
const height = 527; // set your local image height
// calculate image width and height
const screenWidth = Dimensions.get("window").width;
const scaleFactor = width / screenWidth;
const imageHeight = height / scaleFactor;
this.setState({ imgWidth: screenWidth, imgHeight: imageHeight });
};
async componentDidMount() {
Animated.timing(
// Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: 1, // Animate to opacity: 1 (opaque)
duration: 800, // Make it take a while
useNativeDriver: true
}
).start(this.checkLogIn);
}
render() {
const { imgWidth, imgHeight, fadeAnim } = this.state;
return (
<Animated.View
style={{
opacity: fadeAnim,
backgroundColor: "#ebebeb",
flex: 1,
justifyContent: "center",
alignItems: "center"
}}
>
<View>
<Image
source={splashScreen}
style={{ width: imgWidth, height: imgHeight }}
/>
</View>
</Animated.View>
);
}
}
Solution 6:[6]
try this:
pass image uri
and parentWidth (can be const { width } = Dimensions.get("window");
) and voila... you have height auto calculated based on width and aspect ratio
import React, {Component} from 'react';
import FastImage from 'react-native-fast-image';
interface Props {
uri: string;
parentWidth: number;
}
interface State {
calcImgHeight: number;
width: number
aspectRatio: number
}
export default class CustomFastImage extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
calcImgHeight: 0,
width: props.parentWidth,
aspectRatio: 1
};
}
componentDidUpdate(prevProps: Props){
const { aspectRatio, width }= this.state
const { parentWidth} = this.props
if( prevProps.parentWidth !== this.props.parentWidth){
this.setState({
calcImgHeight: aspectRatio * parentWidth,
width: parentWidth
})
}
}
render() {
const {calcImgHeight, width} = this.state;
const {uri} = this.props;
return (
<FastImage
style={{width: width, height: calcImgHeight}}
source={{
uri,
}}
resizeMode={FastImage.resizeMode.contain}
onLoad={(evt) =>
{
this.setState({
calcImgHeight: (evt.nativeEvent.height / evt.nativeEvent.width) * width, // By this, you keep the image ratio
aspectRatio: (evt.nativeEvent.height / evt.nativeEvent.width),
})}
}
/>
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | KetZoomer |
Solution 2 | Nikasv |
Solution 3 | Dharman |
Solution 4 | |
Solution 5 | Durga prasad patra |
Solution 6 | GollyJer |