Skip to content

Commit

Permalink
Intrinsic content size for network image sources of <Image>
Browse files Browse the repository at this point in the history
Summary:
It makes possible to just specify remote url for the <Image> and it will work.
`<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} />`

Reviewed By: javache

Differential Revision: D5196055

fbshipit-source-id: aaf139c4518cc35d1f4cf810bbf0305aad73a55b
  • Loading branch information
shergin authored and facebook-github-bot committed Oct 24, 2017
1 parent 7bd0855 commit f3a3289
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 11 deletions.
37 changes: 27 additions & 10 deletions Libraries/Image/RCTImageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ @implementation RCTImageView

// Whether the latest change of props requires the image to be reloaded
BOOL _needsReload;

CGSize _intrinsicContentSize;
}

- (instancetype)initWithBridge:(RCTBridge *)bridge
Expand Down Expand Up @@ -110,13 +112,7 @@ - (void)dealloc

- (CGSize)intrinsicContentSize
{
// The first `imageSource` defines intrinsic content size.
RCTImageSource *imageSource = _imageSources.firstObject;
if (!imageSource) {
return CGSizeZero;
}

return imageSource.size;
return _intrinsicContentSize;
}

- (void)updateIntrinsicContentSize
Expand Down Expand Up @@ -193,6 +189,12 @@ - (void)setImageSources:(NSArray<RCTImageSource *> *)imageSources
{
if (![imageSources isEqual:_imageSources]) {
_imageSources = [imageSources copy];

// If the first image source contains image size, use it to set up `_intrinsicContentSize`.
// Otherwise we will update `_intrinsicContentSize` right after we have dowloaded image.
// `_intrinsicContentSize` defaults to `{0, 0}` if `_imageSources` is empty.
_intrinsicContentSize = _imageSources.firstObject.size;

[self updateIntrinsicContentSize];
_needsReload = YES;
}
Expand Down Expand Up @@ -250,11 +252,14 @@ - (BOOL)hasMultipleSources

- (RCTImageSource *)imageSourceForSize:(CGSize)size
{
if (![self hasMultipleSources]) {
// If we have less than two sources of if we don't have intrinsic content size,
// we have to return the first source.
if (![self hasMultipleSources] ||
CGSizeEqualToSize(_intrinsicContentSize, CGSizeZero)) {
return _imageSources.firstObject;
}

// Need to wait for layout pass before deciding.
// Corner case for empty size.
if (CGSizeEqualToSize(size, CGSizeZero)) {
return nil;
}
Expand Down Expand Up @@ -301,7 +306,7 @@ - (void)reloadImage
RCTImageSource *source = [self imageSourceForSize:self.frame.size];
_pendingImageSource = source;

if (source && self.frame.size.width > 0 && self.frame.size.height > 0) {
if (source) {
if (_onLoadStart) {
_onLoadStart(nil);
}
Expand Down Expand Up @@ -349,6 +354,8 @@ - (void)reloadImage

- (void)imageLoaderLoadedImage:(UIImage *)loadedImage error:(NSError *)error forImageSource:(RCTImageSource *)source partial:(BOOL)isPartialLoad
{
// Can be called from any queue.

if (![source isEqual:_pendingImageSource]) {
// Bail out if source has changed since we started loading
return;
Expand All @@ -365,8 +372,18 @@ - (void)imageLoaderLoadedImage:(UIImage *)loadedImage error:(NSError *)error for
}

void (^setImageBlock)(UIImage *) = ^(UIImage *image) {
RCTAssertMainQueue();

if (!isPartialLoad) {
self->_imageSource = source;

if (CGSizeEqualToSize(self->_intrinsicContentSize, CGSizeZero) && [source isEqual:self->_imageSources.firstObject]) {
// If we just downloaded an image from the first source and if we don't have `_intrinsicContentSize` yet,
// use actual image size as `_intrinsicContentSize`.
self->_intrinsicContentSize = image.size;
[self updateIntrinsicContentSize];
}

self->_pendingImageSource = nil;
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion RNTester/js/ImageExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,10 +641,19 @@ exports.examples = [
render: function() {
return (
<View>
<Image source={require('./uie_thumb_big.png')} style={{alignSelf: 'center'}} />
<Text>Plain static image without explicitly set size</Text>
<Image
source={require('./uie_thumb_big.png')}
style={{alignSelf: 'center'}}
/>
<Text>Plain network image without explicitly set size</Text>
<Image
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
/>
</View>
);
},
platform: 'ios',
},
{
title: 'MultipleSourcesExample',
Expand Down

0 comments on commit f3a3289

Please sign in to comment.