Подтвердить что ты не робот

Поддерживать соотношение сторон изображения с полной шириной в React Native

У меня есть запрос относительно тега. Я хочу, чтобы изображение занимало всю ширину родительского элемента, которое я использую с помощью alignSelf: stretch, но я также хочу, чтобы высота соответствовала соотношению сторон изображения. Как я могу достичь чего-то подобного?

Итак, я хочу, чтобы указать высоту как отношение ширины изображения.

4b9b3361

Ответ 2

Мне нравится подход 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>
        );
    }
}

Ответ 3

Это на самом деле довольно просто.

Класс 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

Вы можете рассчитать высоту изображения на основе соотношения ширина/высота.

Поэтому, если изображение изначально имеет размер 200x100, после установки его resizeMode для растяжения:

var deviceWidth: Dimensions.get('window').width;

...

myImage {
    width: deviceWidth,
    height: deviceWidth * 0.5
}

Я знаю, может быть, это не лучшая практика, но она мне очень помогла с изображениями всех размеров, которые необходимы для поддержания определенной связи с другими изображениями и т.д.

Ответ 5

Вы можете использовать response-native-scalable-image. Следующий пример сделает работу:

import React from 'react';
import { Dimensions } from 'react-native';
import Image from 'react-native-scalable-image';

const image = <Image width={Dimensions.get('window').width} source={{uri: '<image uri>'}} />;

Ответ 6

<Image
   source={require('../../assets/img/headers/image-1.jpg')}
   style={styles.responsiveImage}
 />

const styles = StyleSheet.create({

  responsiveImage: {
    width: '100%',
    // Without height undefined it won't work
    height: undefined,
    // figure out your image aspect ratio
    aspectRatio: 135 / 76,
  },

});

Ответ 7

Как правило, выполнение следующих действий даст нам изображение, отрисованное до максимальной ширины/высоты в зависимости от ориентации, при сохранении соотношения сторон самого изображения:

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

Использование "Содержать" с resizeMode: равномерно масштабировать изображение (поддерживать пропорции изображения) так, чтобы оба размера (ширина и высота) изображения были равны или меньше соответствующего размера вида (за вычетом отступов).

Обновление: * К сожалению, похоже, что есть общая ошибка с resizeMode "содержать", в частности, при использовании реактивного натива для Android: https://github.com/facebook/react-native/pull/5738 *

Ответ 8

Я попробовал подход 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);
  };
}

Это обновит размеры изображения в соответствии с шириной экрана.

Ответ 9

Вы можете использовать что-то вроде этого:

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

Пожалуйста, обратите внимание, что вам все еще нужно установить высоту на контейнере вида.