我有一个组件,它采用图像道具并进行适当的调整(并在 ScrollView 和 required 资产中工作。在滚动视图中,它使用图像的高度作为高度,无论它是否缩放会导致一些多余的填充。此组件执行大小计算并重新调整图像样式以使用 100% 宽度保持加载文件的纵横比。
import React, { useState } from "react";
import { Image, ImageProps } from "react-native";
export function FullWidthImage(props: ImageProps) {
// Initially set the width to 100%
const [viewDimensions, setViewDimensions] = useState<{
width?: number | string;
height?: number | string;
}>({
width: "100%",
height: undefined,
});
const [imageDimensions, setImageDimensions] = useState<{
width?: number;
height?: number;
}>(() => {
if (typeof props.source === "number") {
// handle case where the source is an asset in which case onLoad won't get triggered
const { width, height } = Image.resolveAssetSource(props.source);
return { width, height };
} else {
return {
width: undefined,
height: undefined,
};
}
});
return (
<Image
onLayout={(e) => {
// this is triggered when the "view" layout is provided
if (imageDimensions.width && imageDimensions.height) {
setViewDimensions({
width: e.nativeEvent.layout.width,
height:
(e.nativeEvent.layout.width * imageDimensions.height) /
imageDimensions.width,
});
}
}}
onLoad={(e) => {
// this is triggered when the image is loaded and we have actual dimensions.
// But only if loading via URI
setImageDimensions({
width: e.nativeEvent.source.width,
height: e.nativeEvent.source.height,
});
}}
{...props}
style={[
props.style,
{
width: viewDimensions.width,
height: viewDimensions.height,
},
]}
/>
);
}
这是为了补偿contain,即使图像宽度为100%,它也会在图像周围添加额外的填充(这基本上是使图像视图高度变满)。
请注意,您可能正试图将其作为背景放入,在这种情况下,ImageBackground 无法在 Android 上正确呈现。使用上面的代码进行了一些调整,我创建了以下内容,可以正确呈现长文本和短文本。
import React, { PropsWithChildren } from "react";
import { ImageProps, View } from "react-native";
import { FullWidthImage } from "./FullWidthImage";
export function FullWidthImageBackground(props: PropsWithChildren<ImageProps>) {
const imageProps = { ...props };
delete imageProps.children;
return (
<View>
<FullWidthImage
{...imageProps}
style={{
position: "absolute",
}}
/>
{props.children}
</View>
);
}
注意如果你使用的是header,你需要添加一个padding view作为第一个child
<View
style={{
height: safeAreaInsets.top + (Platform.OS === "ios" ? 96 : 44),
}}
/>