如何在本机反应中将图像宽度设置为 100% 并将高度设置为自动?

Posted

技术标签:

【中文标题】如何在本机反应中将图像宽度设置为 100% 并将高度设置为自动?【英文标题】:How to set image width to be 100% and height to be auto in react native? 【发布时间】: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 等。上述解决方案几乎可以工作,除了高度不是动态的。部分图像不可见。

【问题讨论】:

看看react-native-scalable-image 【参考方案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这样的静态图像的图像比例。

有很多有用的开源库 -

react-native-auto-height-image react-native-fullwidth-image react-native-fit-image

【讨论】:

它是图像的样式属性,根据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
/>

【讨论】:

正如您所建议的那样,github.com/vivaxy/react-native-auto-height-image 解决了这个问题。谢谢【参考方案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】:

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

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

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

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

     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的图片组件

【讨论】:

以上是关于如何在本机反应中将图像宽度设置为 100% 并将高度设置为自动?的主要内容,如果未能解决你的问题,请参考以下文章

如何在本机反应中将图像读取为二进制/ blob

如何在 WPF 中将宽度设置为 100%

在本机反应中将图像转换为base64

反应本机 minWidth 问题

如何在本机反应中将 <Text> 文本设置为大写

如何在本机反应中将捕获的图像保存到应用程序文件夹?