34

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 :

  • Keep image's ratio.
  • Vertically top positioned.

React native test code :

https://snack.expo.io/ry3_W53rW

Eventually what I want to make :

https://jsfiddle.net/hadeath03/mb43awLr/

Thanks.

Téwa
  • 824
  • 2
  • 11
  • 19

4 Answers4

48

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}}
/>
David Schumann
  • 9,116
  • 6
  • 56
  • 78
dejakob
  • 1,714
  • 12
  • 21
  • Thanks for the answer. So I have to know image size and use Dimensions in order to control image size. – Téwa Jul 19 '17 at 13:15
  • In your expo example, why did you put width: '100%' ? I don't think it's working. – Téwa Jul 19 '17 at 13:19
  • 1
    100% works only in newer versions of React Native (from 0.43 if I'm correctly) – dejakob Jul 19 '17 at 15:22
  • 1
    Future visitors, using `Dimensions` will fail miserably when device is rotated. You need to bind orientation change and reverse width/height. This is not an elegant solution imo. RN should handle this better. – Abdul Sadik Yalcin Feb 16 '20 at 23:18
2

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.

David Schumann
  • 9,116
  • 6
  • 56
  • 78
gtRfnkN
  • 339
  • 5
  • 17
1

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'}} />
Muhammad Usman
  • 1,090
  • 11
  • 22
0

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