使用边距时,带有“{width: 100%, height: auto}”的 React Native Image 组件错位

React Native Image component with "{width: 100%, height: auto}" gets dislocated when using margin

我有一个宽度为 Dimensions.get('window').width 的图像组件, 和使用此公式计算的高度:

{ //not the real code, but it works exactly like this.
  width: Dimensions.get('window').width,
  height: actualImageHeight*(Dimensions.get('window').width/actualImageWidth)
}

它基本上模拟了 width: 100%, height: auto 在 css 中的工作方式。

它工作得很好,直到我给它添加边距,这导致图像错位 像这样: Dislocated Bear

我也尝试过使用 PixelRatio.getPixelSizeForLayoutSize(margin*2) 来尝试考虑边距,这使得新公式看起来像这样:

{ //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)
}

结果差不多了,但还是有点错位:Slightly Dislocated Bear

这让我觉得尺寸不是宽度的好参考。

那么如何模拟不使用 Dimensions 的 width: 100%, height: auto

是否可以将width: 100%作为参考在公式中使用?

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>
 );
};

当您将计算的宽度和高度放置到任何视图时,如果您在样式中放置边距,它会使视图错位,因为在渲染视图时也考虑了边距。最好用视图包裹图像。

我仍然延续了用边距减去宽度的想法,我设法让它起作用了。只需执行 Dimensions.get('window').width-(margin*2) 即可使其工作。所以最终代码是:

{
  width: Dimensions.get('window').width-(margin*2),
  height: actualImageHeight*(Dimensions.get('window').width-(margin*2)/actualImageWidth)
}

结果:Bears

组件的完整代码:

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;