Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full width image using flexbox? #950

Closed
joshbedo opened this issue Apr 21, 2015 · 33 comments · May be fixed by AbhinavJain13/react-native#41
Closed

Full width image using flexbox? #950

joshbedo opened this issue Apr 21, 2015 · 33 comments · May be fixed by AbhinavJain13/react-native#41
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@joshbedo
Copy link

I'm attempting to make an image full-width and came across a few stackoverflow questions related where the top upvoted answer was to use flexbox similarly to how i'm using it below. Although it doesn't seem to display the image unless i set static widths on my styles property. Any ideas?

var styles = StyleSheet.create({
  canvasContainer: {
    flex:1,
    alignItems: 'stretch'
  },
  canvas: {
    flex:1
   // width: 200,
   // height: 200
  }
});
render: function() {
    return (
      <View style={styles.container}>
        <View style={styles.canvasContainer}>
          <Image
            source={{uri: 'http://imgs.steps.dragoart.com/how-to-draw-a-pony-step-7_1_000000053055_5.jpg'}}
            style={styles.canvas} />
        </View>
        <ScrollView
          style={styles.scrollView}
          scrollEventThrottle={200}
          contentInset={{top: 0}}
          >
          {this.state.messages.map(m => {
            return <Text style={styles.message}>Josh: {m}</Text>
          })}
        </ScrollView>
      </View>
    )
  }
@brentvatne
Copy link
Collaborator

canvas: {
  position: 'absolute',
  top: 0,
  left: 0,
  bottom: 0,
  right: 0,
},
<Image
  resizeMode="contain"
  source={{uri: 'http://imgs.steps.dragoart.com/how-to-draw-a-pony-step-7_1_000000053055_5.jpg'}}
  style={styles.canvas} />

Try out stretch and cover for alternative resizeModes too

@brentvatne
Copy link
Collaborator

Here's a full example that integrates it using position: relative in the parent to constrain it:

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
} = React;

var SampleApp = React.createClass({
  render: function() {
    return (
      <View style={{flex: 1, flexDirection: 'row'}}>
        <View style={styles.container}>
          <Image
            resizeMode="contain"
            source={{uri: 'http://imgs.steps.dragoart.com/how-to-draw-a-pony-step-7_1_000000053055_5.jpg'}}
            style={styles.canvas} />
        </View>
        <View style={styles.container}>
          <Text>Hello!</Text>
        </View>
      </View>

    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    position: 'relative'
  },
  canvas: {
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },
});


AppRegistry.registerComponent('SampleApp', () => SampleApp);

screen shot 2015-04-21 at 8 56 29 am

@brentvatne
Copy link
Collaborator

If this doesn't resolve your problem feel free to re-open.

@joshbedo
Copy link
Author

@brentvatne awesome, i actually solved it by changing the container styles around. alignItems:'center' was causing the child image element to not show for some reason.

@miracle2k
Copy link

I can confirm the alignItems fix as well. In general, I find it very fiddly to figure out how combination of properties works, and the results are different depending on whether the source is local or not.

I believe that #2804 (comment) might be related to this also.

@onchainguy-eth
Copy link
Contributor

Seems like you guys were struggeling with the same thing as me. I have an image not showing up though my code pretty much seems to be equal to @joshbedo's first post (see code below). As soon as I add a fixed height like for instance 300 to my imageWrapper style the image shows up. Does anybody have an idea?

import React, { Component, Image, PropTypes, View } from 'react-native'
import Dimensions from 'Dimensions'

let window = Dimensions.get('window')

const prefix = 'http://my-image-server.com/images/'

class MyImage extends Component {
  render() {
    let imageUrl = prefix + this.props.type + '/' + (this.props.size || 1080) + '/' + this.props.filename + '.jpg'

    return (
      <View style={styles.imageWrapper}>
        <Image style={styles.image} source={{uri: imageUrl}}/>
      </View>
    )
  }
}

MyImage.propTypes = {
  type: PropTypes.string.isRequired,
  filename: PropTypes.string.isRequired,
  size: PropTypes.string
}

let styles = {
  imageWrapper: {
    flex: 1,
    alignItems: 'stretch'
  },
  image: {
    flex: 1
  }
}

export default MyImage

@yashvekaria
Copy link

I have done according to this, Hope this code snippet might help you.

<Image style={styles.bgContainer} resizeMode='cover' source={require('./img/bg.png')} />

const styles = StyleSheet.create({ bgContainer: { flex:1, width: null, height: null } });

@tisalph
Copy link

tisalph commented May 12, 2016

Above @yashvekaria solution worked for me

@clinyong
Copy link

I have done without flex.

local image

<View>
  <Image
    style={{height: 100, width: null}}
    source={require('./ad.png')}
  />
</View>

network image

<View>
  <Image
    style={{height: 100}}
    source={{uri: 'http://xxx.com/ad.png'}}
  />
</View>

@mtolly
Copy link

mtolly commented May 26, 2016

@yashvekaria's and @clinyong's solution (adding a width: null) worked for me, and I am very curious as to why. Why is setting it to null different from not setting it at all?

@vinpac
Copy link

vinpac commented Jun 4, 2016

@clinyong How would you do width: 100%, height: auto in react-native?

@PierBover
Copy link

@vini175pa you can use react-native-extended-stylesheet for that, but the problem is that when the devices rotates the values are not updated...

@superandrew213
Copy link

superandrew213 commented Sep 23, 2016

@vinpac try this:

Get image width and height with:

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

Then do this:

<Image
  source={{...}}
  style={{
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').width * this.state.height / this.state.width
  }}
  resizeMode={'cover'}
/>

Not a pretty way, but it works.

@ragamufin
Copy link

ragamufin commented Nov 16, 2016

Hi,

I ran into the same issue as well. Some of the solutions didn't quite work for me. For instance the previous solution by @superandrew213 would have the image filling the width of the window but often you want the image to fill/respect the width of its parent container. Here's what I tried that works:

<View style={{flexDirection:'row'}}>
    <Image 
        source={...} 
        resizeMode="contain" 
        style={{flexShrink:1}}
     />
</View>

The key point is to get the image to be in a row layout using flexDirection:'row' in its container then the image has resizeMode='contain' in order for it to maintain its aspect ratio and style with flexShrink:1 to make sure it doesn't horizontally overflow its container.

@monzerhijazi
Copy link

monzerhijazi commented Nov 21, 2016

Hmm, I noticed that these examples only worked when a flex has been specified for all parent views/components. The image itself needs flex: 1, width: null, height: null at a minimum. Anyways this worked for me to display the image on the top half of the screen:

<View style={{flex: 1}}>
        <View style={{flexDirection: "row", flex: 1}}>
          <Image source={{uri: "https://vestigo.co/images/yoga-outside.jpg"}} style={{flex: 1, resizeMode: "stretch", width: null, height: null}}  />
        </View>
        <View style={{flex: 2}}>
        </View>
</View>

@dc-me
Copy link

dc-me commented Feb 20, 2017

@joshbedo the parent alignItems sets to center , cause the Image not show , does any one knows why? change the parent alignItems and flex:1 for the Image fix the problem for me .

@ragamufin
Copy link

@danywheeler If you set alignItems to "center" on the parent then it changes it from the default "stretch". This causes the image then to not have any space if you don't specify a width and height

@magician11
Copy link

@clinyong your method works great in my iOS simulator.

When I view it via Expo on my Android phone I get

Error while updating property 'width' in shadow node of type: RCTTextInlineImage

Looks like we can't use null. Stackoverflow answer here.

Your solution was so slick.. I'd like to keep using it. Ideas? Is this an Android thing?

@maludwig
Copy link

maludwig commented May 30, 2017

I tried wiping out as many style options as possible and finding the minimal set of styles required to reach the goal. You don't need containers or anything, just an Image. Apparently the "width:null" bit is important:

    <Image 
      style={{ width: null }} 
      resizeMode="contain"
      source={require('./img/catfish.jpg')} 
    />

If you need it to fit with other elements:

    <Image 
      style={{ flex:1, width: null }} 
      resizeMode="contain"
      source={require('./img/catfish.jpg')} 
    />

@magician11
Copy link

Following on from @maludwig 's solution, to get a 100% width image that has a specific height, this works:

<Image
    source={require('../images/space.jpeg')}
    style={{ height: 290, width: null }}
    resizeMode="cover"
/>

@jwtea
Copy link

jwtea commented Jul 17, 2017

Posting this here in case anyone gets in the same trouble as i have.
I wanted to be able to put an image in a container and have it fill to that container. The following seems to work so far in any situation. The view wrapping the image with flexDirection of row is what it all hinges on which may be me just being bad still getting used to flex positioning.

    <View 
    style={{flex:1,flexDirection: 'row'}}>
      <Image
        resizeMode='contain'
        style={{
          flex:1,
          width:null,
          height:null}}
        source={Images[status]}
      />
    </View>

@hailie-rei
Copy link

@jwtea Thank you! Your variant works for me, but I changed resize mode to 'cover' and now it works perfect!

@Noitidart
Copy link

Noitidart commented Sep 8, 2017

Getting <Image> width:100% and height auto is so finicky. Trying on Android right now. Always such a battle.

@ragamufin
Copy link

What I do now is have an image component that based on the width/height of the image it sets the flex properties and such so that I can achieve width 100% without changing the aspect ratio and without the image overflowing its container. The source for my images are set with require('...') so Image.getSize() doesn't work on them but the following does and works synchronously:

const resolveAssetSource = require('resolveAssetSource')
let { width, height } = resolveAssetSource(imageSource)

@abdennour
Copy link

abdennour commented Sep 23, 2017

@jwtea solution is working with me like a charm 🎉 known that I am using flex containers

@Noitidart
Copy link

I gave up and had to create an Image component with onLoad to get the source image/width and then setState to set the image dimensions. I will revisit later, this is too much overhead for something so simple.

@ragamufin
Copy link

@Noitidart Totally agreed. The team made the decision to not mimic the concept of automatically sizing images and maintaining their aspect ratio as it is on the web. I can see the pros for that but boy it sure is a pain to get an image to be width 100% (yet not wider than it's container) while having the height automatically adjust. It's such a common use-case that it would be nice to have something for this out of the box someday

@comur
Copy link

comur commented Dec 8, 2017

For me nothing worked except this approach: https://stackoverflow.com/a/42556256
Other solutions depend top container configurations / styling

@mjstelly
Copy link

I agree with @Noitidart. We've been dealing with image tags since the birth of WWW. Why is it still so difficult and wonky requiring dozens of kludgy workarounds? I've tried nearly every suggestion here. So far, none of them have worked. I'm just venting. So feel free to ignore.

@sparshgr8
Copy link

sparshgr8 commented Feb 20, 2018

How should I proceed, If I have to show full width and auto height of images inside a list (flatlist/sectionlist/listview) like the Instagram app?
The current Examples work well as in Individual Component only, When I put the component inside renderItem of flatlist the images don't show.
<FlatList data={['a', 'b', 'c']}
renderItem={({ item }) => (
<View>
<Text>{item}</Text>
<Image
style={{ flex:1, width: null, height: null } }
resizeMode="contain"
source={{ uri: 'http://www.transphone.net/images/android-transfer/android-screenshot2.jpg'}} />
</View> )}
/>

Any Help is much Appreciated.

@wassgha
Copy link

wassgha commented Mar 27, 2018

Here's a module I made that does exactly this https://www.npmjs.com/package/react-native-fullwidth-image

@aussig
Copy link

aussig commented Apr 11, 2018

I found that @jwtea 's solution almost worked for me (thanks Jack!), but although the image was scaled horizontally, there was excessive automatic padding (whitespace) inserted above and below the image. Adding an aspectRatio with correct values for my image solved this:

<View 
    style={{flex: 1, flexDirection: 'row'}}>
      <Image
        resizeMode='contain'
        style={{
          flex: 1,
          width: null,
          height: null,
          aspectRatio: 926/606}}
        source={Images[status]}
      />
    </View>

In my case my image was 926 wide and 606 high, so I just used those values directly. A more sensible developer might have simplified the aspect ratio of their source image first to e.g. 16/9!

For me, this works across both Android and iOS, tested on a few device sizes.

@onka13
Copy link

onka13 commented May 27, 2018

Here is my solution;

const img = (source) => {
    const { width, height } = Image.resolveAssetSource(source)
    return <Image source={source} style={{ width: null, height: null, resizeMode: 'cover', aspectRatio: width / height }} />
}
<View style={{ flexDirection: 'row' }}>
	<View style={{ flex:2 }}>
		{img(require('./assets/images/1.png'))}
	</View>
	<View style={{ flex:1 }}>
		{img(require('./assets/images/2.png'))}
	</View>
</View>

@facebook facebook locked as resolved and limited conversation to collaborators May 29, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 22, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

Successfully merging a pull request may close this issue.