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

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

175576 次浏览

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>
);
}
});

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.

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.

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

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%'
},]
})

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

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',
},

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',
},
});

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