Add Image resizeMode center to iOS

Summary:
Addresses this comment: https://github.com/facebook/react-native/issues/2296#issuecomment-232446493

This pull request adds the `center` value to `ImageResizeMode`.
When set, it will center the image within its frame.
If the image is larger than its frame, the image is downscaled while maintaining its aspect ratio.
That is how the Android implementation works, too.

Sorry, don't have time to write tests. 😢

Any reviewers should make sure `RCTTargetRect` returns the correct value when:
- the image is smaller than its frame (ie: no downscaling needed)
- the image is larger than its frame (should be downscaled to avoid clipping)
Closes https://github.com/facebook/react-native/pull/8792

Differential Revision: D3586134

Pulled By: javache

fbshipit-source-id: 78fb8e5928284003437dac2c9ad264fa584f73ec
This commit is contained in:
aleclarsoniv 2016-07-19 03:33:37 -07:00 committed by Facebook Github Bot 5
parent d343eaabff
commit bee118096b
4 changed files with 35 additions and 7 deletions

View File

@ -173,7 +173,7 @@ const Image = React.createClass({
* - `repeat`: Repeat the image to cover the frame of the view. The
* image will keep it's size and aspect ratio. (iOS only)
*/
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat']),
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center']),
/**
* A unique identifier for this element to be used in UI Automation
* testing scripts.

View File

@ -53,9 +53,10 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
destSize.height = destSize.width / aspect;
}
// Calculate target aspect ratio if needed (don't bother if resizeMode == stretch)
// Calculate target aspect ratio if needed
CGFloat targetAspect = 0.0;
if (resizeMode != UIViewContentModeScaleToFill) {
if (resizeMode != RCTResizeModeCenter &&
resizeMode != RCTResizeModeStretch) {
targetAspect = destSize.width / destSize.height;
if (aspect == targetAspect) {
resizeMode = RCTResizeModeStretch;
@ -72,12 +73,12 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
if (targetAspect <= aspect) { // target is taller than content
sourceSize.width = destSize.width = destSize.width;
sourceSize.width = destSize.width;
sourceSize.height = sourceSize.width / aspect;
} else { // target is wider than content
sourceSize.height = destSize.height = destSize.height;
sourceSize.height = destSize.height;
sourceSize.width = sourceSize.height * aspect;
}
return (CGRect){
@ -92,7 +93,7 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
if (targetAspect <= aspect) { // target is taller than content
sourceSize.height = destSize.height = destSize.height;
sourceSize.height = destSize.height;
sourceSize.width = sourceSize.height * aspect;
destSize.width = destSize.height * targetAspect;
return (CGRect){
@ -102,7 +103,7 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
} else { // target is wider than content
sourceSize.width = destSize.width = destSize.width;
sourceSize.width = destSize.width;
sourceSize.height = sourceSize.width / aspect;
destSize.height = destSize.width / targetAspect;
return (CGRect){
@ -110,6 +111,26 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
RCTCeilSize(sourceSize, destScale)
};
}
case RCTResizeModeCenter:
// Make sure the image is not clipped by the target.
if (sourceSize.height > destSize.height) {
sourceSize.width = destSize.width;
sourceSize.height = sourceSize.width / aspect;
}
if (sourceSize.width > destSize.width) {
sourceSize.height = destSize.height;
sourceSize.width = sourceSize.height * aspect;
}
return (CGRect){
{
RCTFloorValue((destSize.width - sourceSize.width) / 2, destScale),
RCTFloorValue((destSize.height - sourceSize.height) / 2, destScale),
},
RCTCeilSize(sourceSize, destScale)
};
}
}
@ -131,6 +152,10 @@ CGSize RCTTargetSize(CGSize sourceSize, CGFloat sourceScale,
BOOL allowUpscaling)
{
switch (resizeMode) {
case RCTResizeModeCenter:
return RCTTargetRect(sourceSize, destSize, destScale, resizeMode).size;
case RCTResizeModeStretch:
if (!allowUpscaling) {
@ -207,6 +232,7 @@ BOOL RCTUpscalingRequired(CGSize sourceSize, CGFloat sourceScale,
}
case RCTResizeModeRepeat:
case RCTResizeModeCenter:
return NO;
}

View File

@ -13,6 +13,7 @@ typedef NS_ENUM(NSInteger, RCTResizeMode) {
RCTResizeModeCover = UIViewContentModeScaleAspectFill,
RCTResizeModeContain = UIViewContentModeScaleAspectFit,
RCTResizeModeStretch = UIViewContentModeScaleToFill,
RCTResizeModeCenter = UIViewContentModeCenter,
RCTResizeModeRepeat = -1, // Use negative values to avoid conflicts with iOS enum values.
};

View File

@ -15,6 +15,7 @@ RCT_ENUM_CONVERTER(RCTResizeMode, (@{
@"cover": @(RCTResizeModeCover),
@"contain": @(RCTResizeModeContain),
@"stretch": @(RCTResizeModeStretch),
@"center": @(RCTResizeModeCenter),
@"repeat": @(RCTResizeModeRepeat),
}), RCTResizeModeStretch, integerValue)