Add Image resizeMode repeat on iOS
Summary: This adds a new resize mode for iOS 'repeat' that tiles the image over it's frame. This allow to easily create a view with a repeating background pattern which there is no way to do at the moment without including a bunch of different sized assets. I'm not 100% sure it should be a resizeMode or a separate prop but I went with resizeMode since it made more sense to me and the are not really any use cases where we'd want to use this with another resizeMode other than 'stretch'. **Test plan** Tested mainly by adding a UIExplorer example, also tested that changing the resizeMode prop from and to 'repeat' worked properly. ![screen shot 2016-06-07 at 3 06 17 am](https://cloud.githubusercontent.com/assets/2677334/15848755/d95d8046-2c5c-11e6-9f3d-1ce8a1c9c846.png) I'd like to implement this on Android too but it is a bit trickier since Fresco's ImageView doesn't support image tiling and would require submitting a PR there too :( Closes https://github.com/facebook/react-native/pull/7968 Differential Revision: D3469119 Pulled By: javache fbshipit-source-id: ab9dbfe448a5b0771dbf0c41fcceeb366210f583
This commit is contained in:
parent
0669a38b01
commit
4c83237511
|
@ -505,6 +505,18 @@ exports.examples = [
|
|||
source={image}
|
||||
/>
|
||||
</View>
|
||||
{ Platform.OS === 'ios' ?
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Repeat
|
||||
</Text>
|
||||
<Image
|
||||
style={styles.resizeMode}
|
||||
resizeMode={Image.resizeMode.repeat}
|
||||
source={image}
|
||||
/>
|
||||
</View>
|
||||
: null }
|
||||
{ Platform.OS === 'android' ?
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
|
|
|
@ -126,8 +126,11 @@ const Image = React.createClass({
|
|||
*
|
||||
* 'stretch': Scale width and height independently, This may change the
|
||||
* aspect ratio of the src.
|
||||
*
|
||||
* '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']),
|
||||
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat']),
|
||||
/**
|
||||
* A unique identifier for this element to be used in UI Automation
|
||||
* testing scripts.
|
||||
|
|
|
@ -40,6 +40,12 @@ var ImageResizeMode = keyMirror({
|
|||
* The image will not be scaled up.
|
||||
*/
|
||||
center: null,
|
||||
|
||||
/**
|
||||
* repeat - The image will be repeated to cover the frame of the View. The
|
||||
* image will keep it's size and aspect ratio.
|
||||
*/
|
||||
repeat: null,
|
||||
});
|
||||
|
||||
module.exports = ImageResizeMode;
|
||||
|
|
|
@ -64,6 +64,7 @@ CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
|
|||
|
||||
switch (resizeMode) {
|
||||
case RCTResizeModeStretch:
|
||||
case RCTResizeModeRepeat:
|
||||
|
||||
return (CGRect){CGPointZero, RCTCeilSize(destSize, destScale)};
|
||||
|
||||
|
@ -204,6 +205,10 @@ BOOL RCTUpscalingRequired(CGSize sourceSize, CGFloat sourceScale,
|
|||
|
||||
return destSize.width > sourceSize.width;
|
||||
}
|
||||
|
||||
case RCTResizeModeRepeat:
|
||||
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,5 +22,6 @@
|
|||
@property (nonatomic, assign) UIImageRenderingMode renderingMode;
|
||||
@property (nonatomic, strong) RCTImageSource *source;
|
||||
@property (nonatomic, assign) CGFloat blurRadius;
|
||||
@property (nonatomic, assign) RCTResizeMode resizeMode;
|
||||
|
||||
@end
|
||||
|
|
|
@ -95,11 +95,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
image = [image imageWithRenderingMode:_renderingMode];
|
||||
}
|
||||
|
||||
// Applying capInsets of 0 will switch the "resizingMode" of the image to "tile" which is undesired
|
||||
if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, _capInsets)) {
|
||||
if (_resizeMode == RCTResizeModeRepeat) {
|
||||
image = [image resizableImageWithCapInsets:_capInsets resizingMode:UIImageResizingModeTile];
|
||||
} else if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, _capInsets)) {
|
||||
// Applying capInsets of 0 will switch the "resizingMode" of the image to "tile" which is undesired
|
||||
image = [image resizableImageWithCapInsets:_capInsets resizingMode:UIImageResizingModeStretch];
|
||||
}
|
||||
|
||||
// Apply trilinear filtering to smooth out mis-sized images
|
||||
self.layer.minificationFilter = kCAFilterTrilinear;
|
||||
self.layer.magnificationFilter = kCAFilterTrilinear;
|
||||
|
@ -161,10 +162,19 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
return UIEdgeInsetsEqualToEdgeInsets(_capInsets, UIEdgeInsetsZero);
|
||||
}
|
||||
|
||||
- (void)setContentMode:(UIViewContentMode)contentMode
|
||||
- (void)setResizeMode:(RCTResizeMode)resizeMode
|
||||
{
|
||||
if (self.contentMode != contentMode) {
|
||||
super.contentMode = contentMode;
|
||||
if (_resizeMode != resizeMode) {
|
||||
_resizeMode = resizeMode;
|
||||
|
||||
if (_resizeMode == RCTResizeModeRepeat) {
|
||||
// Repeat resize mode is handled by the UIImage. Use scale to fill
|
||||
// so the repeated image fills the UIImageView.
|
||||
self.contentMode = UIViewContentModeScaleToFill;
|
||||
} else {
|
||||
self.contentMode = (UIViewContentMode)resizeMode;
|
||||
}
|
||||
|
||||
if ([self sourceNeedsReload]) {
|
||||
[self reloadImage];
|
||||
}
|
||||
|
@ -229,7 +239,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
size:imageSize
|
||||
scale:imageScale
|
||||
clipped:NO
|
||||
resizeMode:(RCTResizeMode)self.contentMode
|
||||
resizeMode:_resizeMode
|
||||
progressBlock:progressHandler
|
||||
completionBlock:^(NSError *error, UIImage *loadedImage) {
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ RCT_EXPORT_VIEW_PROPERTY(onProgress, RCTDirectEventBlock)
|
|||
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoadEnd, RCTDirectEventBlock)
|
||||
RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode, RCTResizeMode)
|
||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, RCTResizeMode)
|
||||
RCT_EXPORT_VIEW_PROPERTY(source, RCTImageSource)
|
||||
RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTImageView)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ typedef NS_ENUM(NSInteger, RCTResizeMode) {
|
|||
RCTResizeModeCover = UIViewContentModeScaleAspectFill,
|
||||
RCTResizeModeContain = UIViewContentModeScaleAspectFit,
|
||||
RCTResizeModeStretch = UIViewContentModeScaleToFill,
|
||||
RCTResizeModeRepeat = -1, // Use negative values to avoid conflicts with iOS enum values.
|
||||
};
|
||||
|
||||
@interface RCTConvert(RCTResizeMode)
|
||||
|
|
|
@ -15,6 +15,7 @@ RCT_ENUM_CONVERTER(RCTResizeMode, (@{
|
|||
@"cover": @(RCTResizeModeCover),
|
||||
@"contain": @(RCTResizeModeContain),
|
||||
@"stretch": @(RCTResizeModeStretch),
|
||||
@"repeat": @(RCTResizeModeRepeat),
|
||||
}), RCTResizeModeStretch, integerValue)
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue