I have an Image component that has width from Dimensions.get('window').width
,
and height that is calculated using this formula:
{ //not the real code, but it works exactly like this.
width: Dimensions.get('window').width,
height: actualImageHeight*(Dimensions.get('window').width/actualImageWidth)
}
It basically closely emulates how width: 100%, height: auto
works in css.
and it works well until i added margins to it, which causes the image to get dislocated like this: Dislocated Bear
I have also tried to use PixelRatio.getPixelSizeForLayoutSize(margin*2)
to try taking account the margin, which makes the new formula look like this:
{ //not the real code, but it works exactly like this.
width: Dimensions.get('window').width-PixelRatio.getPixelSizeForLayoutSize(margin*2),
height: actualImageHeight*((Dimensions.get('window').width-PixelRatio.getPixelSizeForLayoutSize(margin*2))/actualImageWidth)
}
and the result is almost, there, but still slightly dislocated: Slightly Dislocated Bear
Which makes me think that Dimensions isn't a good reference for width.
So how do I emulate width: 100%, height: auto
that doesn't use Dimensions?
Is it possible to use width: 100%
as a reference to use in the formula?
CodePudding user response:
import React from 'react';
import {SafeAreaView,View,Dimensions,Image,} from 'react-native';
const {width, height} = Dimensions.get('window');
const actualImageHeight = 200;
const actualImageWidth = 300;
const Test = props => {
return (
<SafeAreaView style={{flex: 1}}>
<View
style={{
width: width,
height: actualImageHeight * (width / actualImageWidth),
borderRadius: 6,
borderWidth: 1,
borderColor: '#f1f1f1',
overflow: 'hidden',
backgroundColor: 'red',
padding: 12,
}}>
<Image
style={{flex: 1, width: null, height: null}}
source={{uri: 'https://picsum.photos/200/300'}}
/>
</View>
</SafeAreaView>
);
};
when you place calculated width and height to any view if you place margin in styles it will dislocated the view because while rendering the view margin also considered. Better to wrap image with view.
CodePudding user response:
I still continued the idea of subtracting the width with the margins, and I managed to make it work. Simply by doing Dimensions.get('window').width-(margin*2)
will make it work. So final code is:
{
width: Dimensions.get('window').width-(margin*2),
height: actualImageHeight*(Dimensions.get('window').width-(margin*2)/actualImageWidth)
}
The result: Bears
Full code of the component:
import React, { useState, useEffect } from "react";
import { Dimensions, Image } from "react-native";
interface AnotherCardProps {
thumbnail: string;
margin?: number;
column?: number;
maxHeight?: number;
minHeight?: number;
}
const AnotherCard: React.FC<AnotherCardProps> = (props) => {
const [imageSize, setImageSize] = useState({ width: 0, height: 0, ratio: 0 });
const margin = props.margin || 0;
const column = props.column || 1;
const newWidth = Dimensions.get("window").width / column - margin * 2;
const maxHeight = props.maxHeight || newWidth * 1.5;
const minHeight = props.minHeight || newWidth;
useEffect(() => {
Image.getSize(props.thumbnail, (w, h) =>
setImageSize({
width: w,
height: h,
ratio: newWidth / w,
})
);
});
return (
<Image
style={{
borderRadius: 20,
margin: margin,
flex: 1,
width: newWidth,
height:
imageSize.height * imageSize.ratio < minHeight
? minHeight
: imageSize.height * imageSize.ratio > maxHeight
? maxHeight
: imageSize.height * imageSize.ratio,
resizeMode: "cover",
}}
source={{
uri: props.thumbnail,
}}
/>
);
};
export default AnotherCard;