Reputation: 1272
I am newbie at react-native.
What I want to do is that fit an image in device and keep the ratio of image. Simply I want to make width : 100%
I searched how to make it and seems resizeMode = 'contain'
is good for that.
However, since I used resizeMode = 'contain'
, the image keeps the position vertically centered which I don't want.
I want it to be vertically top.
I tried to use a plug-in such as react-native-fit-image but no luck.
And I found the reason why the image is not sizing automatically. But still I have no idea how to make it.
So, my question is what is the best way to deal with this situation?
Do I have to manually put width, height
size each images?
I want :
React native test code :
https://snack.expo.io/ry3_W53rW
Eventually what I want to make :
https://jsfiddle.net/hadeath03/mb43awLr/
Thanks.
Upvotes: 48
Views: 111888
Reputation: 1
you can use this method to fill container without any margin
const ImageHandler = ({ name, onPress }: any) => {
const [ImgHeight, setImgHeight] = React.useState(width)
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => onPress()}
style={{
width: width,
height: ImgHeight,
maxHeight:width,
}}
>
<FastImage
onLoad={(e) => {
let newWidth = width
let hei = (e.nativeEvent.height/ e.nativeEvent.width)*newWidth
setImgHeight(hei)
}}
style={{
flex: 1,
width: undefined,
height: undefined,
backgroundColor: colors.white,
}}
resizeMode={Platform.OS === "ios" ? "cover" : "cover"}
source={{ uri: `${Your image url}` }}
/>
</TouchableOpacity>
);
};
Upvotes: 0
Reputation: 12592
One easy way is to not define height for the image and set the width to 100%
. But, its necessary to set resizeMode
to contain
. See example below:
<View>
<Image source={require('../../../assets/stools/type1.png')} resizeMode="contain" style={{width: '100%'}}/>
</View>
This way the aspect ratio is preserved.
To remove the extra space above and below the image, you can set height: 100
or any other number. This will not affect the aspect ratio`
Upvotes: -1
Reputation: 545
You can Apply this style to image: If you apply Image to the Image tag then the Image width full image.
const win = Dimensions.get('window');
export default function App() {
return (
<View style={styles.container}>
<Image
style={{
width: win.width/1,
height: win.width/5,
resizeMode: "contain",
alignSelf: "center",
borderRadius: 20,
}}
source={require('./assets/logo.png')}
/>
</View>
);
}
Upvotes: 2
Reputation: 41740
I have a component that takes image props and does the proper adjustments (and works within a ScrollView
and with require
d assets. Inside a scroll view it uses the height of the image as the height regardless if it is scaled that causes some excess padding. This component performs size computations and readjusts the image style to work with a 100% width preserving the aspect ratio of the file that was loaded.
import React, { useState } from "react";
import { Image, ImageProps } from "react-native";
export function FullWidthImage(props: ImageProps) {
// Initially set the width to 100%
const [viewDimensions, setViewDimensions] = useState<{
width?: number | string;
height?: number | string;
}>({
width: "100%",
height: undefined,
});
const [imageDimensions, setImageDimensions] = useState<{
width?: number;
height?: number;
}>(() => {
if (typeof props.source === "number") {
// handle case where the source is an asset in which case onLoad won't get triggered
const { width, height } = Image.resolveAssetSource(props.source);
return { width, height };
} else {
return {
width: undefined,
height: undefined,
};
}
});
return (
<Image
onLayout={(e) => {
// this is triggered when the "view" layout is provided
if (imageDimensions.width && imageDimensions.height) {
setViewDimensions({
width: e.nativeEvent.layout.width,
height:
(e.nativeEvent.layout.width * imageDimensions.height) /
imageDimensions.width,
});
}
}}
onLoad={(e) => {
// this is triggered when the image is loaded and we have actual dimensions.
// But only if loading via URI
setImageDimensions({
width: e.nativeEvent.source.width,
height: e.nativeEvent.source.height,
});
}}
{...props}
style={[
props.style,
{
width: viewDimensions.width,
height: viewDimensions.height,
},
]}
/>
);
}
This is to compensate for contain
which adds extra padding around the image (which is basically making the image view height full) even if the image width is 100%
.
Note chances are you are trying to put it in as a background, in which case ImageBackground
does not renders correctly on Android. Using the above code a few tweaks I created the following that renders things correctly with long and short text.
import React, { PropsWithChildren } from "react";
import { ImageProps, View } from "react-native";
import { FullWidthImage } from "./FullWidthImage";
export function FullWidthImageBackground(props: PropsWithChildren<ImageProps>) {
const imageProps = { ...props };
delete imageProps.children;
return (
<View>
<FullWidthImage
{...imageProps}
style={{
position: "absolute",
}}
/>
{props.children}
</View>
);
}
Note if you are using it with a header, you need to add a padding view as the first child
<View
style={{
height: safeAreaInsets.top + (Platform.OS === "ios" ? 96 : 44),
}}
/>
Upvotes: 0
Reputation: 378
Right click on you image to get resolution. In my case 1233 x 882
const { width } = Dimensions.get('window');
const ratio = 882 / 1233;
const style = {
width,
height: width * ratio
}
<Image source={image} style={style} resizeMode="contain" />
That all
Upvotes: 0
Reputation: 1258
You can Apply this style to image:
If you apply imageStyle
to the Image
tag then the Image width will be 100% and Image height will be 300.
imageStyle:{
height:300,
flex:1,
width:null
}
Suppose you Image Code is:
<Image style={imageStyle} source={{uri:'uri of the Image'}} />
Upvotes: 2
Reputation: 2102
The image is vertically centered, because you added flex: 1
to the style property. Don't add flex: 1, because that will fill the image to its parent, which is not desired in this case.
You should always add a height and width on an image in React Native. In case the image is always the same, you can use Dimensions.get('window').width
to calculate the size the image should be. For example, if the ratio is always 16x9, the height is 9/16th of the width of the image. The width equals device width, so:
const dimensions = Dimensions.get('window');
const imageHeight = Math.round(dimensions.width * 9 / 16);
const imageWidth = dimensions.width;
return (
<Image
style={{ height: imageHeight, width: imageWidth }}
/>
);
Note: When using an implementation like this, your image will not automatically resize when rotating your device, using split screen, etc. You will have to take care of those actions as well if you support multiple orientations...
In case the ratio is not the same, dynamically change the 9 / 16 by the ratio for each different image. If you don't really bother the image is a little bit cropped, you can use cover mode with a fixed height as well: (https://snack.expo.io/rk_NRnhHb)
<Image
resizeMode={'cover'}
style={{ width: '100%', height: 200 }}
source={{uri: temp}}
/>
Upvotes: 71
Reputation: 489
Just to give this a shot as well
You can also wait for the Image onLayout callback to get it's layout properties and use that to update the dimensions. I created a component for that:
import * as React from 'react';
import { Dimensions, Image, ImageProperties, LayoutChangeEvent, StyleSheet, ViewStyle } from 'react-native';
export interface FullWidthImageState {
width: number;
height: number;
stretched: boolean;
}
export default class FullWidthImage extends React.Component<ImageProperties, FullWidthImageState> {
constructor(props: ImageProperties) {
super(props);
this.state = { width: 100, height: 100, stretched: false };
}
render() {
return <Image {...this.props} style={this.getStyle()} onLayout={this.resizeImage} />;
}
private resizeImage = (event: LayoutChangeEvent) => {
if (!this.state.stretched) {
const width = Dimensions.get('window').width;
const height = width * event.nativeEvent.layout.height / event.nativeEvent.layout.width;
this.setState({ width, height, stretched: true });
}
};
private getStyle = (): ViewStyle => {
const style = [StyleSheet.flatten(this.props.style)];
style.push({ width: this.state.width, height: this.state.height });
return StyleSheet.flatten(style);
};
}
This will update the dimensions of the image to match the width of the screen.
Upvotes: 2