Image 'contain' resizeMode not working in react native - react-native

I am using React Native on a real Android device.
When creating a really simple app with just the following render function on the main app component...
render() {
<Image
source={{uri:'http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg'}}
style={
{
flex: 1,
resizeMode: 'contain',
backgroundColor: 'yellow'
}
} />
}
I get the following result on my device:
As you can see the whole background is yellow so that tells us the image element is taking the whole screen size indeed. But it is just rendered wrong.
The 'cover' resizeMode does work as expected (and so does the 'stretch' mode).
It is the 'contain' mode that is not working (the most important one from my point of view).
The problem gets even worse when placing the image on a ListView since the image does not even show.
UPDATE 1
As Frederick points out, 'contain' only works when the image is larger than the container size. So how can we make the image take the whole container size while keeping its aspect ratio?
Percentages are not supported yet by styles in React, and I don't know how to get the image width and height properties once the image is loaded. None of the events associated with the Image component provide that info.
UPDATE 2
Good news. I am now using React Native v0.24.1 and it seems the image 'contain' mode now works as expected, even when the actual image size is smaller than its container.
zvona's solution is good (although you need to bear in mind that onLayout will give you the image view size the image is rendered in, but NOT the actual image size being loaded). As for now, I don't know of any way to find out the actual image size (let's suppose you are retrieving the image from a network resource and you don't know the size, which could be very important if you want to calculate its aspect ratio).

This is the trick:
render() {
return (
<Image
style={{ flex: 1, height: undefined, width: undefined }}
source={require("../../resource/image/bg_splash.jpg")}
resizeMode="contain"
/>
);
}

This is the latest solution:
Image.resizeMode.contain is not working with latest version of react native so i use it like this:
import ImageResizeMode from 'react-native/Libraries/Image/ImageResizeMode'
<Image source={image} resizeMode={ImageResizeMode.contain} />

This is what worked for me with the latest react-native 0.37:
<Image source={require('../images/my-image.png')} resizeMode={Image.resizeMode.center} />
Answering the updated part of the question. You can get the image size for external images using Image.getSize.
For local images, a not so documented way to figure out the size and thereby calculate the aspect ratio is using resolveAssetSource which is a react-native module (no need for an external library):
let resolveAssetSource = require('resolveAssetSource')
let { width, height } = resolveAssetSource(image_source)
let aspectRatio = width / height

My answer to UPDATED part of the question:
<Image source={{uri:'...'}} onLayout={this.onImageLayout} />
where:
onImageLayout: function(data){
console.log('layout', data.nativeEvent.layout);
}
These should be proportioned to device width + height, which you get with:
const {
Dimensions,
.
.
.
} = React;
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;
And if you want to get width/height as percentages in styles, you just define e.g.:
const styles = StyleSheet.create({
image: {
width: windowWidth * 0.75,
height: windowHeight * 0.33
}
});

"Contain" only resizes your image when the image size is larger than the container you're trying to fit it in. In this case, your container is the full screen. The image you're loading via the URL is way smaller, since it's only 53 by 77 pixels. So it won't resize.
I think "cover" should do what you're trying to achieve. However, due to the size the image, it won't look very nice when it is magnified like that.
Made an example here: https://rnplay.org/apps/X5eMEw

Adding the aspect ratio worked for me:
<Image
source={item.imageUrl && item.imageUrl != '' ? { uri: item.imageUrl } : require('../../assets/images/no-image-icon-15.png')}
style={{
flex: 1,
aspectRatio: 1.5,
height: undefined,
width: undefined
}}
resizeMode="contain"
/>

I will suggest you a simple solution to apply if it's convenient for you.
use "ImageBackground" component of react-native.
so your code will become something like this:
<ImageBackground
source={{uri:'http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg'}}
style={{flex: 1}} />
In your particular case you are apparently trying to cover whole screen with the image so this solution is exactly for that purpose. However most of the time it works in other cases as well where you want to fit the image properly in its view.

Related

round image in react native without zoom effect

I have the following code :
<Image
style={styles.avatar}
source={{
uri: `${BASE_URL}/avatars/${userAvatar}`,
}}
resizeMode="cover"
/>
and for styling :
avatar: {
width: 70,
height: 70,
borderRadius: 50,
marginRight: "5%",
},
That code works and displays the image in a circle shape.
The problem is that the image is "zoomed" more or less depending on the difference concerning is native height and width.
For instance, if I use an image like this one :
https://www.artmajeur.com/medias/hd/a/n/anib/artwork/12741944_humboldt-pinguin-1.jpg
I can't see the head of the pinguin.
If I use the resizeMode="contain" instead of cover, I am not able to get a circle shape.
Plus, I have read that android required the "cover" value.
How can I do to see the whole image (more or less) in a circle shape ?
If you want the maintain the dimensions of avatar and see the whole image as well, then you could use resizeMode="stretch".
<Image
style={styles.avatar}
source={{
uri: `${BASE_URL}/avatars/${userAvatar}`,
}}
resizeMode="stretch"
/>
Depending on the image, this might not look appealing. However, unless you know exactly what images you need to display, there is no way to know which parts of the images you want to zoom in. This is the reason why most applications that allow for example an avatar image require the user to select the section of the image if the aspect ration does not match.
Notice, that the image container still has the circular shape if using a different resizeMode. However, the image itself will not have this shape. We can test this by setting a background color.

React Native Samsung One UI 3.0 Dimensions screen width not returning correct value

I'm using react native 0.63.4 and I use <View style={{flex: 1}}> for the root element of every page.
I use Dimensions.get("screen").width to make the elements responsive. For some reason the value of screen width is not correct but a larger value. Thus every element on the screen gets larger.
Expected behavior:
Expected image.
Issue: issue image
I've tested with many devices. I see this problem only on Galaxy S20 Ultra and S10 Lite. The issue occurred after installing the Android 11 & OneUi 3.0 update.
Code:
const {height: screen_height, width: screen_width} = Dimensions.get('screen');
<View style={{ flex: 1,justifyContent:"center",alignItems:"center" }}>
<Text style={{fontSize:screen_width/15}}>text</Text>
</View>;
What could cause the problem?
UPDATE: The issue appears only when the device's screen resolution is set to 3200x1440. The app works as expected on lower resolutions.
Replace this code:
const {height: screen_height, width: screen_width} = Dimensions.get('screen');
With this:
let scale = Dimensions.get('screen').scale / Dimensions.get('window').scale;
const screen_height = Dimensions.get('window').height * scale;
const screen_width = Dimensions.get('window').width * scale;
try Dimensions.get("window").height and Dimensions.get("window").width can resolve your case.
I think your text components are overlapping the actual viewport. Could you add the code which renders the actual (text) content?
And if it causes the issue, then you could try to wrap it with flexWrap: 'wrap' style property.

Why do gaps appear when I set borderLeftWidth=1 in react-native?

I have the following react-native code which does exactly what I want because it prints a solid black rectangle:
getTable() {
const cell = {
backgroundColor:'black',
flex:1,
height:50,
};
const table = {
borderColor:'black',
borderLeftWidth:0,
borderRightWidth:0,
borderTopWidth:0,
borderBottomWidth:0,
width:'100%'};
return (
<View style={table}>
<View style={{flexDirection:"row"}}>
<View style={cell}></View>
<View style={cell}></View>
<View style={cell}></View>
</View>
</View>
);
}
However, when I change the table.borderLeftWidth to a value of 1, I see a white vertical line 66% from the left of the black box as depicted in this image:
Why does adding a border left to the container cause a white line to the interior content?
This issue happens in all iOS devices and all iOS simulated devices. It does not appear in Android. What am I doing wrong?
Based on the fact that this issue only occurs on iOS devices I'd suspect it's an issue with the iOS implementation. The react-native issue #2089 on GitHub seems to be similar to what you're encountering.
The issue lies in react-native's "implementation" of CSS on iOS devices (since it's not actually CSS) and that it's simply a rendering bug (probably with flexbox). I'd recommend that you post about your issue there and see if they can resolve it.

Nativebase : change thumbnail default size

I can't change the default size of the thumbnail from NativeBase. I can display the default circle, which is the small and the large one, but I want to display a bigger circle than the default size. Here's my code for the thumbnail :
<Thumbnail size={200} style={{margin: 30}} source={require('../../../public/images/profile/yellow.jpg')} />
The props size doesn't work, the thumbnail remains small.
My NativeBase version : 2.3.5
Native Base Component doesn't have a size props, you should add width and height, and one more thing you shouldn't forget please add borderRadius divided by 2 to ensure the shape is retain Circle
<Thumbnail style={{width: 30, height: 30, borderRadius: 30/2}} source={require('../../../public/images/profile/yellow.jpg')} />
You can simply increase the Thumbnail size by using this trick. Just take the property of scale with <Thumbnail/>.
Just copy-paste the below code in your app
<Thumbnail
scaleX={3} scaleY={3} style={{margin: 30}}
source={require('../../../public/images/profile/yellow.jpg')}/>
You can change the scale values as per your need. Let me know if this fixes your issue.
The Thumbnail component from NativeBase doesn't have the size attribute. Try to set width and height properties of the style attribute
<Thumbnail style={{width: 100, height: 100, margin: 30}} source={require('../../../public/images/profile/yellow.jpg')} />
NativeBase Thumbnail component comes with small and large props for size. You can also set width and height to have image with other dimensions

React Native: Keyboard blocks multiline textInput when adjusting its view's height

I've been trying to make a growing textinput with multiple lines now for a while, and is now finding my app in a situation where the keyboard blocks the text when entering a new line on the textinput. I've tried solutions ranging from KeyboardAwareScrollView-based solutions to ScrollView solutions, but alas nothing I've tried yet have worked.
I would really appreciate if someone could provide me with a solution that works for both android and iOS.
What I have now is a view with a textinput with multiline prop
<View style={{ height: this.state.height, flex: 1 }}>
<TextInput
{...otherProps}
placeholder="Skriv här"
placeholderTextColor="rgba(0,0,0,0.3)"
blurOnSubmit={false}
multiline
onContentSizeChange={this._onContentSizeChange}
style={[styles.textInputStyle, { height: this.state.height }]}
/>
</View>
with the _onContentSizeChange function as follows:
_onContentSizeChange = (event): void => {
const height = event.nativeEvent.contentSize.height;
this.setState({ height });
}
Problem illustrated with pictures:
imgur album
KeyboardAvoidingView seems to be the solution for you. You can set the distance between your view and the keyboard and calculate it with the height of your input. In the docs you find all properties: https://facebook.github.io/react-native/docs/keyboardavoidingview.html
You can also try using KeyboardAvoidingScrollView, then when your input is high enough you just scroll down the screen.
Here's an awesome article with great examples of keyboard avoids: https://medium.freecodecamp.org/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580
Hope it helps.