【问题标题】:How to set image width to be 100% and height to be auto in react native?如何在本机反应中将图像宽度设置为 100% 并将高度设置为自动?
【发布时间】:2017-01-30 14:37:52
【问题描述】:

我正在尝试在滚动视图中显示图像列表。宽度应该是 100%,而高度应该是自动的,保持纵横比。

我所做的搜索指向了提供全屏背景样式的各种解决方案。

const styles = StyleSheet.create({
    image: {
        width: null,
        height: 300,
        resizeMode: 'cover'
    }
});

<ScrollView style={{flex: 1}}>
    <Image style={styles.image} source={require('../../../images/collection-imag1.png')}/>
    <Image style={styles.image} source={require('../../../images/collection-imag2.png')}/>
</ScrollView>

我尝试了各种宽度组合:null,高度:null,flex:1,alignSelf 等。上述解决方案几乎可以工作,除了高度不是动态的。部分图像不可见。

【问题讨论】:

标签: javascript image reactjs react-native


【解决方案1】:

所以经过一段时间的思考,我能够达到 height: auto in react-native image。 您需要知道图像的尺寸才能使此 hack 起作用。只需在任何图像查看器中打开您的图像,您就会在文件信息中获得图像的尺寸。 作为参考,我使用的图像尺寸为 541 x 362

首先从 react-native 导入维度

import { Dimensions } from 'react-native';

那么你必须得到窗口的尺寸

const win = Dimensions.get('window');

现在计算比率为

const ratio = win.width/541; //541 is actual image width

现在为您的图像添加样式

imageStyle: {
    width: win.width,
    height: 362 * ratio, //362 is actual height of image
}

【讨论】:

  • 你是天才。我仍然无法弄清楚这一点。但它有效:)
  • 这么聪明的解决方案
  • 截至 2020 年 3 月,这仍然是最佳解决方案吗?
  • 是的!这是唯一一个在所有情况下都有效的。唯一要考虑的是,如果这些是静态资产,您可以很容易地解析图像尺寸。只需:import myImage from '../../assets/myimage.png'; const { width, height } = Image.resolveAssetSource(myImage)
  • 非常感谢。它也适用于 2021 年。为什么 React 团队从来没有构建一些功能来让开发人员更容易做到这一点?
【解决方案2】:

"resizeMode" 不是样式属性。应该移动到 Image 组件的Props,如下面的代码。

const win = Dimensions.get('window');

const styles = StyleSheet.create({
    image: {
        flex: 1,
        alignSelf: 'stretch',
        width: win.width,
        height: win.height,
    }
});

...
    <Image 
       style={styles.image}
       resizeMode={'contain'}   /* <= changed  */
       source={require('../../../images/collection-imag2.png')} /> 
...

图像的高度不会自动生成,因为在style props 中,图像 组件的宽度和高度都需要。所以你可以使用getSize()方法来计算像this answer这样的远程图像,你也可以计算像this answer这样的静态图像的图像比例。

有很多有用的开源库 -

【讨论】:

  • 它是图像的样式属性,根据facebook.github.io/react-native/docs/image.html。将其更改为属性也不起作用。
  • 这不能回答自动计算高度的给定问题
  • 这行得通,但你应该说你需要“从'react-native'导入{Dimensions};”
  • 这并不能从很多角度回答这个问题。除了上述 cmets 中所说的之外,the doc 明确表示 getSize() “不适用于静态图像资源”。
  • @Betty 我认为 getSize() 确实适用于静态图像。
【解决方案3】:

如果您知道图像的 aspectRatio (width / height),我已经找到了 width: "100%", height: "auto" 的解决方案。

代码如下:

import { Image, StyleSheet, View } from 'react-native';

const image = () => (
    <View style={styles.imgContainer}>
        <Image style={styles.image} source={require('assets/images/image.png')} />
    </View>
);

const style = StyleSheet.create({
    imgContainer: {
        flexDirection: 'row'
    },
    image: {
        resizeMode: 'contain',
        flex: 1,
        aspectRatio: 1 // Your aspect ratio
    }
});

这是不使用onLayoutDimension 计算的最简单方法。如果需要,您甚至可以将其包装在一个简单的可重用组件中。如果有人正在寻找简单的实现,请试一试。

【讨论】:

    【解决方案4】:

    我对上述所有解决方案都有疑问。最后我使用 aspectRatio 来解决这个问题。当您知道图像的宽度和高度并且它们很大时,只需计算 aspectRatio 并将其添加到图像中,如下所示:

    <PhotoImage
        source={{uri: `data:image/jpeg;base64,${image.base64}`}}
        style={{ aspectRatio: image.width / image.height }}
     />
    

    AspectRatio 是 React Native 的一个布局属性,用于保持图像的纵横比并适合父容器:https://facebook.github.io/react-native/docs/layout-props#aspectratio

    【讨论】:

    • 这是唯一真正的答案。对此进行扩展。如果您从网络请求图像。您可以使用来自react-nativeImage.getSize 静态方法获取大小
    【解决方案5】:

    在样式中使用 aspectRatio 属性

    纵横比控制节点未定义维度的大小。纵横比是一个非标准属性,仅在 react native 中可用,在 CSS 中不可用。

    • 在具有设置宽度/高度纵横比的节点上控制 未设置的维度
    • 在具有设置弹性基准纵横比的节点上控制 如果未设置,则在交叉轴上的节点
    • 在具有测量函数纵横比的节点上,就像 measure 函数测量弹性基础
    • 在具有 flex 增长/收缩纵横比的节点上控制 如果未设置,则在交叉轴上的节点
    • 纵横比考虑了最小/最大尺寸

    文档:https://reactnative.dev/docs/layout-props#aspectratio

    试试这样:

    import {Image, Dimensions} from 'react-native';
    
    var width = Dimensions.get('window').width; 
    
    <Image
        source={{
            uri: '<IMAGE_URI>'
        }}
        style={{
            width: width * .2,  //its same to '20%' of device width
            aspectRatio: 1, // <-- this
            resizeMode: 'contain', //optional
        }}
    />
    

    【讨论】:

      【解决方案6】:

      您始终必须设置Image 的宽度和高度。它不会自动为您调整大小。 React Native 文档says so

      您应该使用onLayout 测量ScrollView 的总高度,并根据它设置Images 的高度。如果您使用resizeModecover,它将保持Images 的纵横比,但如果它比容器大,它显然会裁剪它们。

      【讨论】:

      • 仅自动调整大小不适用于远程图像。 OP 正在引用一个本地的静态图像文件,用 React Native 的话 “可以自动调整大小,因为它们的尺寸在安装时立即可用。”
      【解决方案7】:

      2020 年 4 月解决方案:

      所以上面的答案很可爱,但他们都有一个很大的缺陷(imo):他们正在计算图像的高度,基于用户设备的宽度

      要拥有一个真正响应式(即width: 100%, height: auto)实现,您真正想要做的是计算图像的高度,基于在父容器的宽度上。

      幸运的是,React Native 为我们提供了一种获取父容器宽度的方法,这要感谢onLayout View method

      所以我们需要做的就是用width: "100%"创建一个View,然后用onLayout得到那个view的宽度(即容器宽度),然后用那个容器宽度来适当地计算我们图像的高度.

       

      给我看代码...

      可以通过使用RN's Image.getSize 进一步改进以下解决方案,以在 ResponsiveImage 组件本身中获取图像尺寸。

      JavaScript:

      // ResponsiveImage.ts
      
      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;
      
      
      // Example usage...
      
      import ResponsiveImage from "../components/ResponsiveImage";
      
      ...
      
      <ResponsiveImage
        src={require("./images/your-image.jpg")}
        srcWidth={910} // replace with your image width
        srcHeight={628} // replace with your image height
      />
      

       

      TypeScript:

      // ResponsiveImage.ts
      
      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;
      
      
      // Example usage...
      
      import ResponsiveImage from "../components/ResponsiveImage";
      
      ...
      
      <ResponsiveImage
        src={require("./images/your-image.jpg")}
        srcWidth={910} // replace with your image width
        srcHeight={628} // replace with your image height
      />
      

      【讨论】:

      【解决方案8】:

      右键单击您的图像以获得分辨率。在我的情况下 1233 x 882

      const { width } = Dimensions.get('window');
      
      const ratio = 882 / 1233;
      
          const style = {
            width,
            height: width * ratio
          }
      
      <Image source={image} style={style} resizeMode="contain" />
      

      全部

      【讨论】:

        【解决方案9】:

        对于图像标签,您可以使用这种样式,它对我有用:

        imageStyle: {
            width: Dimensions.get('window').width - 23,
            resizeMode: "contain",
            height: 211,
         },
        

        【讨论】:

        • resizeMode 不能是样式
        • @KaushilRuparelia 绝对可以
        【解决方案10】:

        让我分享一下我最终得到的结果,它允许通过获取图像尺寸来正确设置宽度或高度。此外,该代码允许在传输我们需要的大图像数据时获取加载图像:

        1. 使用静态方法 Image.prefetch 下载图像并用于缓存。

        2. 使用静态方法Image.getSize收集高度和宽度,并用它来计算纵横比,然后计算最终高度(或宽度)

        3. 以您喜欢的宽度显示具有默认样式的图像(高度将在保持纵横比的情况下计算)

           function ImageX(props: {source: string, id: string})
           {
             const [imageHeight, setImageHeight] = React.useState(1);
             Image.prefetch(props.source)
             .then(() => {
                 Image.getSize(props.source, (width, height) => {
                   let aspectRatio =  height/width;
                   setImageHeight(aspectRatio*Dimensions.get('window').width);
                 });
             })
             .catch(error => console.log(error))
             if (imageHeight <=1) //Image not in cache (disk) yet
               {
                 return (
                   <Image key={props.id} style={styleimg.image} source={{uri: 'http://www.dsdsd/loaderpreview.gif'}}/>
                 );
             }
             else
             {
               return (
                 <Image key={props.id} style={styleimg.image} height={imageHeight} source={{uri: props.source}}/>
               );
             }
           }
          

          const styleimg = StyleSheet.create({ 图片: { 宽度:Dimensions.get('window').width, 调整大小模式:'包含' //... // 您可以设置高度默认值 } });

        【讨论】:

          【解决方案11】:

          这可能有助于自动调整具有 100% 宽度的图像高度

          图片:{ 宽度:“100%”, resizeMode:“中心”“包含”, 高度:未定义, 纵横比:1, }

          【讨论】:

            【解决方案12】:

            function ImageX( props){
               const [state, setState] = React.useState({v:{height:1}});
               useEffect(() => {
                if(!props.source || !props.source.uri) return;
                Image.prefetch(props.source.uri)
                .then(() => {
                    Image.getSize(props.source.uri, (width, height) => {
                      let aspectRatio =  height/width;
                      state.v.width=Dimensions.get('window').width;
                      state.v.height=aspectRatio*state.v.width;
                      setState({...state});
                    });
                })
                .catch(error => console.log(error))
               },[props.source && props.source.uri]);
               
               if (state.v.height <=1) //Image not in cache (disk) yet
                 {
                  return (
                    <Image {...props}/>
                  );
               }
               else
               {
                 let neededst={v:{width:state.v.width, height:state.v.height}}
                 let st={v:props.style};
                assignObject(neededst, st);
                 return (
                   <Image {...props} style={neededst.v}/>
                 );
               }
             }
            
             function assignObject(target, source) {
              if (!source) return;
              for (let k in target) {
                let v = target[k];
                if (Object(v) === Object) assignObject(v, source[k]);
                else {
                  if (source[k]) {
                    try {
                      Object.assign(v, source[k]);
                    } catch (e) {
                      alert(e);
                    }
                  }
                }
              }
            
              for (let k in source) {
                if (!target[k]) {
                  target[k] = source[k];
                }
              }
            
            }

            使用来自https://reactnativeelements.com/docs/image的图片组件

            【讨论】:

              猜你喜欢
              • 2014-05-10
              • 2018-10-19
              • 1970-01-01
              • 2020-03-03
              • 1970-01-01
              • 2014-05-26
              • 1970-01-01
              • 2018-10-14
              • 1970-01-01
              相关资源
              最近更新 更多