2020年4月的解决方案:
上面提供的答案都很好,但它们都有一个(在我看来)很大的缺陷:它们是根据用户设备的宽度计算图像的高度。
要实现真正响应式(即width: 100%, height: auto
)的实现,您需要根据父容器的宽度计算图像的高度。
幸运的是,React Native提供了一种方法来获取父容器的宽度,这得益于onLayout View method。
因此,我们所需要做的就是创建一个具有width: "100%"
属性的View,然后使用onLayout
方法获取该视图的宽度(即容器宽度),然后使用该容器宽度适当地计算图像的高度。
直接展示代码。。。
通过在ResponsiveImage组件本身内部使用RN的Image.getSize方法,以下解决方案可以进一步改进。
JavaScript:
import React, { useMemo, useState } from "react";
import { Image, StyleSheet, View } from "react-native";
const ResponsiveImage = props => {
const [containerWidth, setContainerWidth] = useState(0);
const _onViewLayoutChange = event => {
const { width } = event.nativeEvent.layout;
setContainerWidth(width);
}
const imageStyles = useMemo(() => {
const ratio = containerWidth / props.srcWidth;
return {
width: containerWidth,
height: props.srcHeight * ratio
};
}, [containerWidth]);
return (
<View style={styles.container} onLayout={_onViewLayoutChange}>
<Image source={props.src} style={imageStyles} />
</View>
);
};
const styles = StyleSheet.create({
container: { width: "100%" }
});
export default ResponsiveImage;
import ResponsiveImage from "../components/ResponsiveImage";
...
<ResponsiveImage
src={require("./images/your-image.jpg")}
srcWidth={910}
srcHeight={628}
/>
TypeScript:
import React, { useMemo, useState } from "react";
import {
Image,
ImageSourcePropType,
LayoutChangeEvent,
StyleSheet,
View
} from "react-native";
interface ResponsiveImageProps {
src: ImageSourcePropType;
srcWidth: number;
srcHeight: number;
}
const ResponsiveImage: React.FC<ResponsiveImageProps> = props => {
const [containerWidth, setContainerWidth] = useState<number>(0);
const _onViewLayoutChange = (event: LayoutChangeEvent) => {
const { width } = event.nativeEvent.layout;
setContainerWidth(width);
}
const imageStyles = useMemo(() => {
const ratio = containerWidth / props.srcWidth;
return {
width: containerWidth,
height: props.srcHeight * ratio
};
}, [containerWidth]);
return (
<View style={styles.container} onLayout={_onViewLayoutChange}>
<Image source={props.src} style={imageStyles} />
</View>
);
};
const styles = StyleSheet.create({
container: { width: "100%" }
});
export default ResponsiveImage;
import ResponsiveImage from "../components/ResponsiveImage";
...
<ResponsiveImage
src={require("./images/your-image.jpg")}
srcWidth={910}
srcHeight={628}
/>