null
null

Reputation: 111

Automatically size image components in React Native

I want to set the width of an Image component to be 100% of my container's width and the height to be set according to the result width value and image's aspect ratio.

My container has some padding, which means that Dimensions.get('window').width is not useful to me since it does not gives me the value that results from image's width being set to 100%. Other scenarios also can't afford the Dimensions API as a acceptable solution.

Here's an code example:

<View
  style={{
    flex: 1,
    paddingHorizontal: 20,
  }}>
  <Image
    style={{
      flex: 1, // Not what I want => just so I can see the image
      width: '100%',
      // height: 'auto', // The behavior that I want
      backgroundColor: 'red',
    }}
    resizeMode={'contain'}
    source={{
      uri: 'https://via.placeholder.com/200x400/000000',
    }}
  />
</View>

Result:

app

The red background serves just to visualize that the Image component.

Using onLayout prop I can get the runtime value of the resulting width, and with the aid of the Image API i could calculate the desired height. The problem with that is that React Native will first render a 0 height component and just after that onLayout seems to be resolved, and that makes sense.

So?

Notes: - In the image docs of React Native there is an explanation of why they chose not to size image components automatically by default. - At least in this case, Parent onLayout is resolved after its children.

Upvotes: 0

Views: 2030

Answers (1)

Charlie
Charlie

Reputation: 1042

In your componentDidMount you could calculate the image metrics, and then use that height and width to calculate the aspectRatio.

componentDidMount = () => {
   Image.getSize(YourUri, (width, height) => {
      this.setState({width, height});
    });
}

In your image you will add the styles like this:

  <Image
    style={{
      width: '100%',
      backgroundColor: 'red',
      aspectRatio: this.state.height !== null ? this.state.width / this.state.height : 1
    }}
    resizeMode={'contain'}
    source={{
      uri: 'https://via.placeholder.com/200x400/000000',
    }}
  />

As stated in React native docs:

Aspect ratio controls the size of the undefined dimension of a node. Aspect ratio is a non-standard property only available in React Native and not CSS.

-On a node with a set width/height aspect ratio controls the size of the unset dimension

-On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset

-On a node with a measure function aspect ratio works as though the measure function measures the flex basis

-On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset

Aspect ratio takes min/max dimensions into account

Upvotes: 3

Related Questions