From d826e2cf002c3409e70af7ef535cf9f1d9e9dc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Tue, 23 Jun 2015 18:12:06 +0800 Subject: [PATCH 1/3] [Image] Add scale support for base64-encoded image. --- Examples/UIExplorer/TabBarIOSExample.js | 3 +++ React/Base/RCTConvert.m | 22 +++++++++++++++++----- React/Views/RCTTabBarItem.m | 12 +++++++----- React/Views/RCTTabBarItemManager.m | 2 +- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Examples/UIExplorer/TabBarIOSExample.js b/Examples/UIExplorer/TabBarIOSExample.js index 12ca22e78a9bbc..d96bb2d9ac3995 100644 --- a/Examples/UIExplorer/TabBarIOSExample.js +++ b/Examples/UIExplorer/TabBarIOSExample.js @@ -23,6 +23,8 @@ var { View, } = React; +var base64Icon = 'data:image/jpeg;base64,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' + var TabBarExample = React.createClass({ statics: { title: '', @@ -53,6 +55,7 @@ var TabBarExample = React.createClass({ barTintColor="#3abeff"> { this.setState({ diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 804faf87ece82b..fded2a98f79074 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -619,17 +619,24 @@ + (UIImage *)UIImage:(id)json return nil; } - if (RCT_DEBUG && ![json isKindOfClass:[NSString class]]) { + if (RCT_DEBUG && ![json isKindOfClass:[NSString class]] && ![json isKindOfClass:[NSDictionary class]]) { RCTLogConvertError(json, "an image"); return nil; } - if ([json length] == 0) { - return nil; + UIImage *image; + NSString *path; + CGFloat scale = 0.0; + if ([json isKindOfClass:[NSString class]]) { + if ([json length] == 0) { + return nil; + } + path = json; + } else { + path = json[@"path"]; + scale = [self CGFloat:json[@"scale"]]; } - UIImage *image = nil; - NSString *path = json; if ([path hasPrefix:@"data:"]) { NSURL *url = [NSURL URLWithString:path]; NSData *imageData = [NSData dataWithContentsOfURL:url]; @@ -642,6 +649,11 @@ + (UIImage *)UIImage:(id)json image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:nil]]; } } + + if (scale > 0) { + image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; + } + // NOTE: we don't warn about nil images because there are legitimate // case where we find out if a string is an image by using this method return image; diff --git a/React/Views/RCTTabBarItem.m b/React/Views/RCTTabBarItem.m index e6caa0b18453de..8b058622ff40e4 100644 --- a/React/Views/RCTTabBarItem.m +++ b/React/Views/RCTTabBarItem.m @@ -25,7 +25,7 @@ - (UITabBarItem *)barItem return _barItem; } -- (void)setIcon:(NSString *)icon +- (void)setIcon:(id)icon { static NSDictionary *systemIcons; static dispatch_once_t onceToken; @@ -48,13 +48,15 @@ - (void)setIcon:(NSString *)icon // Update icon BOOL wasSystemIcon = (systemIcons[_icon] != nil); - _icon = [icon copy]; + if ([icon isKindOfClass:[NSString class]]) { + _icon = [icon copy]; + } // Check if string matches any custom images first - UIImage *image = [RCTConvert UIImage:_icon]; + UIImage *image = [RCTConvert UIImage:icon]; UITabBarItem *oldItem = _barItem; if (image) { - + // Recreate barItem if previous item was a system icon if (wasSystemIcon) { _barItem = nil; @@ -67,7 +69,7 @@ - (void)setIcon:(NSString *)icon } else { // Not a custom image, may be a system item? - NSNumber *systemIcon = systemIcons[icon]; + NSNumber *systemIcon = systemIcons[_icon]; if (!systemIcon) { RCTLogError(@"The tab bar icon '%@' did not match any known image or system icon", icon); return; diff --git a/React/Views/RCTTabBarItemManager.m b/React/Views/RCTTabBarItemManager.m index cdfa8669ce98d5..d1a96ef2ae4c92 100644 --- a/React/Views/RCTTabBarItemManager.m +++ b/React/Views/RCTTabBarItemManager.m @@ -22,7 +22,7 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(selected, BOOL); -RCT_EXPORT_VIEW_PROPERTY(icon, NSString); +RCT_EXPORT_VIEW_PROPERTY(icon, id); RCT_REMAP_VIEW_PROPERTY(selectedIcon, barItem.selectedImage, UIImage); RCT_REMAP_VIEW_PROPERTY(badge, barItem.badgeValue, NSString); RCT_CUSTOM_VIEW_PROPERTY(title, NSString, RCTTabBarItem) From bb549a2b89d19e459364f6b6aebc7a97db87f06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Tue, 23 Jun 2015 19:40:29 +0800 Subject: [PATCH 2/3] Revert the TabBar example. --- Examples/UIExplorer/TabBarIOSExample.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/Examples/UIExplorer/TabBarIOSExample.js b/Examples/UIExplorer/TabBarIOSExample.js index d96bb2d9ac3995..12ca22e78a9bbc 100644 --- a/Examples/UIExplorer/TabBarIOSExample.js +++ b/Examples/UIExplorer/TabBarIOSExample.js @@ -23,8 +23,6 @@ var { View, } = React; -var base64Icon = 'data:image/jpeg;base64,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' - var TabBarExample = React.createClass({ statics: { title: '', @@ -55,7 +53,6 @@ var TabBarExample = React.createClass({ barTintColor="#3abeff"> { this.setState({ From 9f2ced82c7dbeec3179aacacab671f2db56e0c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= Date: Wed, 24 Jun 2015 16:02:48 +0800 Subject: [PATCH 3/3] [Image] Change the image data key to uri and change the tabbar icon class to id. --- React/Base/RCTConvert.m | 2 +- React/Views/RCTTabBarItem.h | 2 +- React/Views/RCTTabBarItem.m | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index fded2a98f79074..5073f1ec8eda94 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -633,7 +633,7 @@ + (UIImage *)UIImage:(id)json } path = json; } else { - path = json[@"path"]; + path = [self NSString:json[@"uri"]]; scale = [self CGFloat:json[@"scale"]]; } diff --git a/React/Views/RCTTabBarItem.h b/React/Views/RCTTabBarItem.h index 0e2433c3c28cb9..8fe6d8efbd64a1 100644 --- a/React/Views/RCTTabBarItem.h +++ b/React/Views/RCTTabBarItem.h @@ -11,7 +11,7 @@ @interface RCTTabBarItem : UIView -@property (nonatomic, copy) NSString *icon; +@property (nonatomic, copy) id icon; @property (nonatomic, assign, getter=isSelected) BOOL selected; @property (nonatomic, readonly) UITabBarItem *barItem; diff --git a/React/Views/RCTTabBarItem.m b/React/Views/RCTTabBarItem.m index 8b058622ff40e4..6855c1410b6ad8 100644 --- a/React/Views/RCTTabBarItem.m +++ b/React/Views/RCTTabBarItem.m @@ -48,12 +48,10 @@ - (void)setIcon:(id)icon // Update icon BOOL wasSystemIcon = (systemIcons[_icon] != nil); - if ([icon isKindOfClass:[NSString class]]) { - _icon = [icon copy]; - } + _icon = [icon copy]; // Check if string matches any custom images first - UIImage *image = [RCTConvert UIImage:icon]; + UIImage *image = [RCTConvert UIImage:_icon]; UITabBarItem *oldItem = _barItem; if (image) { @@ -69,7 +67,7 @@ - (void)setIcon:(id)icon } else { // Not a custom image, may be a system item? - NSNumber *systemIcon = systemIcons[_icon]; + NSNumber *systemIcon = systemIcons[icon]; if (!systemIcon) { RCTLogError(@"The tab bar icon '%@' did not match any known image or system icon", icon); return;