react-native - Fit Image in containing View, not the whole screen size

JavascriptReactjsFlexboxReact Native

Javascript Problem Overview


I'm trying to fit images in their containing views so that I can have a seamless grid of images. The problem is that resizeMode='contain' seems to fit to the width of the screen or at least some higher level container, I need the images to fit to the size of each list item.

Here's a very ugly example of the styles and resulting grid:

The styles:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'blue'
  },
  
  item: {
    flex: 1,
    overflow: 'hidden',
    alignItems: 'center',
    backgroundColor: 'orange',
    position: 'relative',
    margin: 10
  },

  image: {
    flex: 1
  }
})

The layout:

<TouchableOpacity 
  activeOpacity={ 0.75 }
  style={ styles.item }
>
  <Image
    style={ styles.image }
    resizeMode='contain'
    source={ temp }
  /> 
</TouchableOpacity>

The result (with resizeMode='contain'):

enter image description here

The result (with resizeMode='cover'):

enter image description here

As you can see, the covered images are very big and are as wide as the whole screen and don't fit the immediately containing view.

Update 1:

I was able to achieve a result close to what I'm looking for by applying a scale transform to the image and shrinking it from the center:

The transform:

transform: [{ scale: 0.55 }]

The resulting layout (without margins or paddings): enter image description here

Javascript Solutions


Solution 1 - Javascript

If you know the aspect ratio for example, if your image is square you can set either the height or the width to fill the container and get the other to be set by the aspectRatio property

Here is the style if you want the height be set automatically:

{
    width: '100%',
    height: undefined,
    aspectRatio: 1,
}

Note: height must be undefined

Edit (Based on @rob-art's comment):
If your image is a different aspect ratio than the one you want to set in the style you can use resizeMode to control how the image should be displayed. Use resizeMode:'contain' to ensure your image is not cropped.
See documentation for more details

Solution 2 - Javascript

Set the dimensions to the View and make sure your Image is styled with height and width set to 'undefined' like the example below :

    <View style={{width: 10, height:10 }} >
      <Image style= {{flex:1 , width: undefined, height: undefined}}    
       source={require('../yourfolder/yourimage')}
        />
    </View>

This will make sure your image scales and fits perfectly into your view.

Solution 3 - Javascript

Anyone over here who wants his image to fit in full screen without any crop (in both portrait and landscape mode), use this:

image: {
    flex: 1,
    width: '100%',
    height: '100%',
    resizeMode: 'contain',
},

Solution 4 - Javascript

I could not get the example working using the resizeMode properties of Image, but because the images will all be square there is a way to do it using the Dimensions of the window along with flexbox.

Set flexDirection: 'row', and flexWrap: 'wrap', then they will all line up as long as they are all the same dimensions.

I set it up here

https://snack.expo.io/HkbZNqjeZ

"use strict";

var React = require("react-native");
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  TouchableOpacity,
  Dimensions,
  ScrollView
} = React;

var deviceWidth = Dimensions.get("window").width;
var temp = "http://thumbs.dreamstime.com/z/close-up-angry-chihuahua-growling-2-years-old-15126199.jpg";
var SampleApp = React.createClass({
  render: function() {
    var images = [];

    for (var i = 0; i < 10; i++) {
      images.push(
        <TouchableOpacity key={i} activeOpacity={0.75} style={styles.item}>
          <Image style={styles.image} source={{ uri: temp }} />
        </TouchableOpacity>
      );
    }

    return (
      <ScrollView style={{ flex: 1 }}>
        <View style={styles.container}>
          {images}
        </View>
      </ScrollView>
    );
  }
});

Solution 5 - Javascript

Simply You need to pass resizeMode like this to fit in your image in containing view

<Image style={styles.imageStyle} resizeMode={'cover'} source={item.image}/>

const style = StyleSheet.create({
  imageStyle: {
      alignSelf: 'center',
      height:'100%', 
      width:'100%'
    },]
})

Solution 6 - Javascript

I think it's because you didn't specify the width and height for the item.

If you only want to have 2 images in a row, you can try something like this instead of using flex:

item: {
    width: '50%',
    height: '100%',
    overflow: 'hidden',
    alignItems: 'center',
    backgroundColor: 'orange',
    position: 'relative',
    margin: 10,
},

This works for me, hope it helps.

Solution 7 - Javascript

This is working for me,

<Image style={styles.imageStyle} resizeMode="cover" source={imageSource} />

const styles = StyleSheet.create({
  imageStyle: {
    width: undefined,
    height: '100%',
    aspectRatio: 1,
    alignSelf: 'center',
  },
});

Solution 8 - Javascript

the image has a property named Style ( like most of the react-native Compponents) and for Image's Styles, there is a property named resizeMode that takes values like: contain,cover,stretch,center,repeat

most of the time if you use center it will work for you

Solution 9 - Javascript

You can use the "Resize Matters" library which always fix the image scaling.

import { scale, verticalScale } from 'react-native-size-matters';

export const Component = props =>
    <Image style={{
        width: scale(30),
        height: verticalScale(50)
    }}/>;

Here you will be happy: https://github.com/nirsky/react-native-size-matters

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBarakChamoView Question on Stackoverflow
Solution 1 - Javascriptsazzy4oView Answer on Stackoverflow
Solution 2 - JavascriptNaadiya AhmedView Answer on Stackoverflow
Solution 3 - JavascriptcmcodesView Answer on Stackoverflow
Solution 4 - JavascriptNader DabitView Answer on Stackoverflow
Solution 5 - JavascriptSujeetView Answer on Stackoverflow
Solution 6 - Javascriptuser3685578View Answer on Stackoverflow
Solution 7 - JavascriptAljohn YamaroView Answer on Stackoverflow
Solution 8 - Javascriptnoshad b.eView Answer on Stackoverflow
Solution 9 - JavascriptMahmoud Al-Saleh - View Answer on Stackoverflow