Intrinsic content size for network image sources of <Image>

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
This commit is contained in:
Valentin Shergin 2017-10-23 19:37:33 -07:00 committed by Facebook Github Bot
parent 7bd0855650
commit f3a32895ca
7 changed files with 37 additions and 11 deletions

View File

@ -81,6 +81,8 @@ static NSDictionary *onLoadParamsForSource(RCTImageSource *source)
// Whether the latest change of props requires the image to be reloaded
BOOL _needsReload;
CGSize _intrinsicContentSize;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
@ -110,13 +112,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (CGSize)intrinsicContentSize
{
// The first `imageSource` defines intrinsic content size.
RCTImageSource *imageSource = _imageSources.firstObject;
if (!imageSource) {
return CGSizeZero;
}
return imageSource.size;
return _intrinsicContentSize;
}
- (void)updateIntrinsicContentSize
@ -193,6 +189,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
{
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;
}
@ -250,11 +252,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (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;
}
@ -301,7 +306,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
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);
}
@ -349,6 +354,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (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;
@ -365,8 +372,18 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
}
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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

@ -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',