Image Resize Cover - Keep Top Left of Image - react-native

I have a big image that needs to be cropped on certain devices, but it's very important that the top left of my image stays in tact because it has some important content.
<View style={{flex:1}}>
<Image source={MY_IMAGE}
resizeMode="cover"
style={{
flex: 1.8,
width: null,
height: null
}}
/>
<View style={{ flex: 1 }}>
//other content
</View>
</View>
^This is very close to what I want, but by default it looks like resizeMode:"Cover" just zooms in on the center of the image, cutting off my important content.
Is there any way to complete the image resizing based on something like x:0, y: screenHeight so that it keeps the top left of my image and resizes from the bottom right?

Import necessary packages
import { StyleSheet, Image, Dimensions } from 'react-native';
Your img element
<Image style={styles.images} resizeMode="stretch" source={{ uri: 'src here' }} />
Add this styles at the bottom
const styles = StyleSheet.create({
images: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').width / 2
}
});
Try this the image width will be dynamically set even when you rotate your device.

Related

Issue with images styling inside a FlatList - React Native

I'm trying to design an application screen (I used React Navigation) where several images are displayed vertically inside a FlatList. Each image takes up around 90% of the screen, is centered and has some border-radius, to see the other images, the user has to scroll down.
All these things I was able to do myself, the only problem is, when I scroll down the first image, there is a huge empty gap at the top before showing image 2, and when I scroll down again to see image 3, the bottom bit of image 2 is still showing in the upper part of the screen, separated by another huge gap and the bottom of image 3 is cut out of the screen.
What I've been trying to do is to show exactly one full image at a time, and I don't know whether there's something wrong with the scrolling itself, or the styling I applied to the components.
Here's the code:
import {View, FlatList, Image, Dimensions} from 'react-native';
import {pictures} from './pictures.js';
const ImageScreen = () => {
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('screen').height;
function renderImages(pictures){
return(
<View style={{ width: deviceWidth, height: deviceHeight, alignItems:'center'}}>
<Image source={{uri: pictures.item.imageId}}
style={{height:'90%',width:'90%', borderRadius:22 }}/>
</View>
);}
return(
<FlatList data={pictures} keyExtractor={(item)=> item.id} renderItem={renderImages}
pagingEnabled={true} />
);
};
export default SightOverview;
please find below code to display list:
import * as React from 'react';
import { View, FlatList, Image, Dimensions } from 'react-native';
const App = () => {
const pictures = [{
imageId: 'https://picsum.photos/id/1/200/300'
}]
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('screen').height;
function renderImages({ item }) {
console.log(item)
return (
<View style={{ flex: 1, width: deviceWidth, height: deviceHeight, alignItems: 'center' }}>
<Image source={{ uri: item.imageId }}
style={{ width: deviceWidth * 0.8, height: deviceHeight * 0.5, borderRadius: 22 }} />
</View>
);
}
return (
<View style={{ flex: 1 }}>
<FlatList data={pictures} keyExtractor={(item) => item.id} renderItem={renderImages}
pagingEnabled={true} />
</View>
);
};
export default App;

Get coordinates of touch event relative to Image

I have an image centered on the screen. I need to make it touchable and I need to get the coordinates of the touch event relative to the image. I have wrapped my image in a TouchableOpacity to make it touchable. The problem is that the touch coordinates are relative to the TouchableOpacity and not the Image. The TouchableOpacity is taking up the entire screen but the Image is centered inside it.
I either need to make my TouchableOpacity the same size as the Image, or I need to know the offset of the Image within the TouchableOpacity.
I have tried using OnLayout and the NativeEvent object to get the position of the Image within it's parent but it just returns 0,0.
const {width, height} = Dimensions.get("window");
class Inspection extends React.Component {
handlePress(evt) {
// do stuff
...
}
render() {
return (
<View style={{flex:1, backgroundColor:'#fff'}}>
<TouchableOpacity
onPress={(evt) => this.handlePress(evt)}
style={{backgroundColor: '#3897f0'}}
>
<Image
onLayout={({nativeEvent}) => {
console.log(nativeEvent.layout);
}}
source={require('../../images/wireframe-car.jpg')}
resizeMode='contain'
style={{
maxHeight: height,
maxWidth: width
}}
/>
</TouchableOpacity>
</View>
);
}
}
Console Output:
{height: 683.4285888671875, width: 411.4285583496094, y: 0, x: 0}
I've added a backgroundColor to TouchableOpacity so you can see that it takes up the entire screen.
Is there another way of doing this?
TouchableOpacity would be the same size as of the Image because you haven't given any height to it, you simply need to assign onLayout prop to your TouchableOpacity like this
<View
style={{ flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' }}>
<TouchableOpacity
onLayout={({ nativeEvent }) => {
console.log(nativeEvent.layout)
}}
style={{}}
onPress={evt => this.handlePress(evt)}>
<Image
source={require('../../images/wireframe-car.jpg')}
resizeMode="contain"
style={{
maxWidth: '100%',
}}
/>
</TouchableOpacity>
</View>
This will give you the exact x and y of Image.
Update
The problem is also with image size, since the image size is quite big so it takes the height of the device and we get x:0 and y:0, in order to resolve this issue we can give the Image component a static height or calculate its height according to width. We can get width and height image from local path like this:
let imageUri = Image.resolveAssetSource(require('../../images/wireframe-car.jpg').uri)
Image.getSize(imageUri , (width, height) => {
console.log(`The image dimensions are ${width}x${height}`);
}, (error) => {
console.error(`Couldn't get the image size: ${error.message}`);
});

React Native: print full image in a Scrollview

I have an image that is very tall, but not very large. I want to print it in a scrollview, so you can see it all on one screen, but nothing works.
after playing with widths and heights and flexs for my scrollview and my image, the best result I get is when I have on of them with style={{width='100%'}}, like that
<ScrollView style={{width: '100%'}}>
<Image
source={require('./assets/skeleton/fullSkeleton.png')}
resizeMode='cover'
/>
</ScrollView>
which prints the image at full width, but the scrollview's height is the original image's height, which doesn't let me see the whole resized image.
Here, a bad drawing to represent my image, and what I want to see on my phone screen
EDIT:
With this bit of code:
<ScrollView
contentContainerStyle={{alignItems: 'center'}}>
<Image
source={require('./fullSkeleton.png')}
resizeMode='cover'
/>
</ScrollView>
I end up with
Which can be scrolled down to see the rest of the Image. As you can see, it can be navigated vertically, but doesn't take the whole screen's width
This kind of thing in Reat Native is actually quite tricky. But you can do it easily; First get picture dimensions:
const FullWidthPicture = ({ uri }) => {
const [ratio, setRatio] = useState(1);
useEffect(() => {
if (uri) {
Image.getSize(uri, (width, height) => {
setRatio(width / height);
});
}
}, [uri]);
return (
<Image
style={{ width: '100%', height: undefined, aspectRatio: ratio }}
resizeMode="contain"
source={{ uri }}
/>
);
};
And use it like this:
<ScrollView style={{flex: 1}}>
<FulWidthImage uri={pictureUri} />
</ScrollView>
The following may help:
You can use contentContainerStyle to style the contents of the ScrollView. Like this (essentially what you have):
<ScrollView
contentContainerStyle={{alignItems: 'center'}}>
<Image
source={require('./fullSkeleton.png')}
resizeMode='cover'
/>
</ScrollView>
That works for me - I can scroll down the whole image and at the bottom it stays visible.
NB: To make the image cover the whole screen while maintaining the height required, you will need to set the width specifically. In my case on iPhone 7+ that meant adding style={{width: 414}} to the Image component AND changing resizeMode to 'stretch'.
Here is the official take on Image resizing...and getting device dimensions will be useful here too.

Center Image React Native Loading Screen

Background
I have an image placed on a screen meant to show when the screen loads other content.
I want to center the image so it is always center on all devices.
Problem
Currently the image shows up top center. I would like it to be aligned vertically as well. Also to be sure that it will always look the same on all devices.
Question
What is the solution to make sure the image is always centered and the right size for all devices?
Example,
My current code,
In Photoshop
Image is 300 Resolution
Height is 776 px
Width is 600 px
I want the image to be centered horizontally and vertically in all devices and look good without pixelating. Natively I know I need to set the image sizes. But from my understanding in React Native I can use on image but then use JSX to handle it being responsive.
import React from 'react';
import {
StyleSheet,
View,
Image,
} from 'react-native';
const logo = require('../images/logo.jpg');
const LoadingScreen = () => (
<View>
<Image
style={styles.logo}
source={logo}
/>
</View>
);
const styles = StyleSheet.create({
logo: {
justifyContent: 'center',
alignItems: 'center',
width: 300,
height: 400,
},
});
export default LoadingScreen;
You need to set the style of <View> for justifyContent and alignItems for centering the <Image>.
Should be like this :
const LoadingScreen = () => (
<View style={styles.container}>
<Image
style={styles.logo}
source={logo}
/>
</View>
);
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 300,
height: 400,
},
});
Or you can use alignSelf on the <Image> to make it center, but it will still need to add justifyContent on <View> to make it center vertically.
The View container should have styling as
flexDirection: 'column'
justifyContent: 'center'
alignItems: 'center'
height: '100%'
The height makes sure it spans throughout the page, thus making the image become both vertically and horizontally aligned.
For the image size, I think using percentage will do the trick instead of defining definite width/height.
Set in view:
justifycontent:center
And in child:
alignself:center
And perform in task.
Set in parent view:
justifycontent:center
And in child set:
alignself:center

How can I get the image width to fill the card and the height to be flexible?

I'm trying to set the dimensions of the image so that the width will always take up the full width of the card (minus the horizontal margin) and with a flexible height, so that it can scale as it needs to.
How can I do this? It seems that the style needs a height, it won't accept null.
I have tried a LOT of combinations using various resizeModes, heights, widths etc.
Here is the component:
And here is my current code:
renderImage(image) {
const { width, height } = Dimensions.get('window');
if (image) {
return (
<View style={styles.imageContainer}>
<Image
style={{ width, resizeMode: 'contain', height: 300 }}
source={{ uri: image }}
/>
</View>
);
}
}
The aspectRatio property solves this problem nicely.
<Image
style={{ width: '100%', aspectRatio: 1 }}
source={{uri: 'https://online.picture/dynamic_size'}}/>
I had same problem for images from web (where no exact width & height was known) and created react-native-web-image. Currently not for local images, only for remote. Try it, I will be glad if it will help.
Set the width to be the screen width, and set height to be undefined.