在React Native中保持全宽图像的纵横比

时间:2015-04-15 06:07:23

标签: react-native

我有关于标记的查询。我想要一个图像占据父对象的整个宽度,我使用alignSelf:stretch,但我也希望高度根据图像的纵横比。我怎样才能实现这样的目标呢?

所以我想要一种方法来指定高度作为图像宽度的比例。

13 个答案:

答案 0 :(得分:29)

我喜欢 bdv 的方法,我几乎在我的应用中使用这种图像。这就是为什么我创建了一个使用onLayout来支持设备轮换的自有组件。



import resolveAssetSource from 'resolveAssetSource';
import React, {Component} from 'react';
import {Image, View} from 'react-native';

export default class FullWidthImage extends Component {
    constructor() {
        super();

        this.state = {
            width: 0,
            height: 0
        };
    }

    _onLayout(event) {
        const containerWidth = event.nativeEvent.layout.width;

        if (this.props.ratio) {
            this.setState({
                width: containerWidth,
                height: containerWidth * this.props.ratio
            });
        } else if (typeof this.props.source === 'number') {
            const source = resolveAssetSource(this.props.source);

            this.setState({
                width: containerWidth,
                height: containerWidth * source.height / source.width
            });
        } else if (typeof this.props.source === 'object') {
            Image.getSize(this.props.source.uri, (width, height) => {
                this.setState({
                    width: containerWidth,
                    height: containerWidth * height / width
                });
            });
        }
    }

    render() {
        return (
            <View onLayout={this._onLayout.bind(this)}>
                <Image
                    source={this.props.source}
                    style={{
                        width: this.state.width,
                        height: this.state.height
                    }} />
            </View>
        );
    }
}
&#13;
&#13;
&#13;

你可以像这样使用它:

<FullWidthImage source={{uri: 'http://example.com/image.jpg'}} />
<FullWidthImage source={require('./images/image.jpg')} />

或者,如果您知道这样的比例:

<FullWidthImage source={{uri: 'http://example.com/image.jpg'}} ratio={0.5} />
<FullWidthImage source={require('./images/image.jpg')} ratio={0.5} />

答案 1 :(得分:25)

style={{ aspectRatio: 3/2 }}用于宽高比为3:2的水平图像。

文档:https://facebook.github.io/react-native/docs/layout-props.html#aspectratio

(可在RN 0.40 +中使用)

答案 2 :(得分:15)

Ã

答案 3 :(得分:8)

实际上非常简单。

Image类有getSize方法。 [1]

假设您已为aspectRatioImage创建了一个组件,并且每次componentWillMount触发时都会计算出适当的值。

然后你的代码看起来像这样:

componentDidMount() {
    Image.getSize(this.props.source.uri, (srcWidth, srcHeight) => {
      const maxHeight = Dimensions.get('window').height; // or something else
      const maxWidth = Dimensions.get('window').width;

      const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
      this.setState({ width: srcWidth * ratio, height: srcHeight * ratio });
    }, error => {
      console.log('error:', error);
    });
  }

现在,图像的高度和宽度都保存在组件的状态中,您只需运行

即可
 <Image
   style={{ width: this.state.width, height: this.state.height }}
   source={this.props.source}
   resizeMode="cover"
 />

[1] - https://facebook.github.io/react-native/docs/image.html#getsize

答案 4 :(得分:5)

您可以根据宽高比来计算图像高度。

因此,如果图像最初为200x100,则将其resizeMode设置为拉伸:

    const emitter = Platform.OS == 'ios' ? NativeAppEventEmitter : DeviceEventEmitter;
    emitter.addListener("myProgressEvent", (e:Event)=>{
        console.log("myProgressEvent " + JSON.stringify(e));
        if (!e) {
            return;
        }
        this.setState({progress: e.progress});
    });                                                                                             

我知道也许这不是最好的做法,但它对我所有大小的图像都有很大的帮助,需要与其他图像保持某种关系等。

答案 5 :(得分:3)

就我而言,我还必须将高度设置为'auto':

{
    width: 200,
    height: 'auto',
    aspectRatio: 16 / 9,
}

答案 6 :(得分:1)

通常,执行以下操作会为我们提供根据方向渲染到最大宽度/高度的图像,同时保持图像本身的纵横比:

render(){
    return(<Image style={{'width': Dimensions.get('window').width, 
                         'height': Dimensions.get('window').height}}
                  resizeMode='contain'
                  source='[URL here]'
           </Image>);
}

使用&#39;包含&#39;使用resizeMode:均匀缩放图像(保持图像的纵横比),使图像的尺寸(宽度和高度)等于或小于视图的相应尺寸(减去填充)。

更新:*不幸的是,似乎resizeMode存在一个常见的错误&#39;包含&#39;特别是当使用Android的native native时:https://github.com/facebook/react-native/pull/5738 *

答案 7 :(得分:0)

我尝试了 Image.getSize 方法,但遇到了问题,因为我们收集了配置文件中的所有图像链接,然后将ImageURISource传递给Image的源支柱。

我的解决方案是等待Image onLayout回调获取它的布局属性并使用它来更新尺寸。我为此创建了一个组件:

import * as React from 'react';
import { Dimensions, Image, ImageProperties, LayoutChangeEvent, StyleSheet, ViewStyle } from 'react-native';

export interface FullWidthImageState {
  width: number;
  height: number;
  stretched: boolean;
}

export default class FullWidthImage extends React.Component<ImageProperties, FullWidthImageState> {
  constructor(props: ImageProperties) {
    super(props);

    this.state = { width: 100, height: 100, stretched: false };
  }

  render() {
    return <Image {...this.props} style={this.getStyle()} onLayout={this.resizeImage} />;
  }

  private resizeImage = (event: LayoutChangeEvent) => {
    if (!this.state.stretched) {
      const width = Dimensions.get('window').width;
      const height = width * event.nativeEvent.layout.height / event.nativeEvent.layout.width;
      this.setState({ width, height, stretched: true });
    }
  };

  private getStyle = (): ViewStyle => {
    const style = [StyleSheet.flatten(this.props.style)];
    style.push({ width: this.state.width, height: this.state.height });
    return StyleSheet.flatten(style);
  };
}

这将更新图像的尺寸以匹配屏幕的宽度。

答案 8 :(得分:0)

就我而言,我在我的React Native(v0.62 +)项目中使用Styled Components

我需要为具有定义的aspectRatio和未定义的Image的{​​{1}}个组件指定一个正方形width

我发现样式height实现了我想要的“方形图片”结果:

height:0;

此方法也适用于全宽度图像样式-用// Gallery container styled-component const Gallery = styled.View` flexDirection:row; flexWrap:wrap; ` // Square half-width image styled-component const Photo = styled.Image` width:50%; height:0; aspectRatio:1; ` 替换width:50%会产生期望的结果,并且每幅图像的纵横比都正确。

答案 9 :(得分:0)

如果要使用maxWidth:

      <View style={{maxWidth:300}}>
      <Image
        source={logo}
        style={{
          width:"100%",
          resizeMode:"contain",
          height: undefined,
          // maxWidth:200,
          aspectRatio: 16 / 9,
        }} />
      </View>

感谢@Hoenoe

答案 10 :(得分:0)

const RespImage = ({ offer }) => {

const [height, setHeight] = useState(0);
const [width, setWidth] = useState(0);

    let image_url = `YOUR_IMAGE_URI`;

    Image.getSize(image_url, (srcWidth, srcHeight) => {

        const maxHeight = Dimensions.get('window').height;
        const maxWidth = Dimensions.get('window').width;

        const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
        setHeight(srcHeight * ratio);
        setWidth(srcWidth * ratio);
    });

    return (
        <View>
            <Image resizeMode={'contain'} style={{ height: height, width: width, marginBottom: 20, resizeMode: "contain" }}
                source={{ uri: image_url }}
            />
        </View>
    )

}

答案 11 :(得分:-2)

使用resizeMode='contain'

<Image style={{height:'100%', width:'100%'}} resizeMode="contain" source={{uri:this.state.imgSource}} />

这将保持原始的宽高比,并以给定的宽度和高度为max-height和max-width。

答案 12 :(得分:-5)

您可以使用以下内容:

<View style={{height:200}} >
<Image source={require('image!MyImage') style={{ resizeMode:Image.resizeMode.ratio, flex:1 }}} />
</View>

请注意,您仍然需要在视图容器上设置高度。