diff --git a/Examples/UIExplorer/RCTRootViewIOSExample.js b/Examples/UIExplorer/RCTRootViewIOSExample.js index 4a32cc01a..174dcf2bb 100644 --- a/Examples/UIExplorer/RCTRootViewIOSExample.js +++ b/Examples/UIExplorer/RCTRootViewIOSExample.js @@ -24,6 +24,7 @@ var { var requireNativeComponent = require('requireNativeComponent'); var UpdatePropertiesExampleView = requireNativeComponent('UpdatePropertiesExampleView'); +var FlexibleSizeExampleView = requireNativeComponent('FlexibleSizeExampleView'); class AppPropertiesUpdateExample extends React.Component { render() { @@ -42,6 +43,23 @@ class AppPropertiesUpdateExample extends React.Component { } } +class RootViewSizeFlexibilityExample extends React.Component { + render() { + return ( + + + Press the button to resize it. On resize, RCTRootViewDelegate is notified. You can use it to handle content size updates. + + + + Error: This demo is accessible only from UIExplorer app + + + + ); + } +} + var styles = StyleSheet.create({ container: { flex: 1, @@ -63,7 +81,15 @@ exports.examples = [ title: 'Updating app properties in runtime', render(): React.Component { return ( - + + ); + }, +}, +{ + title: 'RCTRootView\'s size flexibility', + render(): React.Component { + return ( + ); }, }]; diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj index 43495b3ed..274b0a0ad 100644 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj +++ b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ 14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; }; 14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; }; 272E6B3F1BEA849E001FCF37 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; settings = {ASSET_TAGS = (); }; }; + 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; settings = {ASSET_TAGS = (); }; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 3D36915B1BDA8CBB007B22D8 /* uie_thumb_big.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D36915A1BDA8CBB007B22D8 /* uie_thumb_big.png */; }; 3DB99D0C1BA0340600302749 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */; }; @@ -225,6 +226,8 @@ 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = ""; }; 272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = ""; }; 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UpdatePropertiesExampleView.m; path = UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.m; sourceTree = ""; }; + 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlexibleSizeExampleView.m; path = UIExplorer/NativeExampleViews/FlexibleSizeExampleView.m; sourceTree = ""; }; + 27F441EA1BEBE5030039B79C /* FlexibleSizeExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlexibleSizeExampleView.h; path = UIExplorer/NativeExampleViews/FlexibleSizeExampleView.h; sourceTree = ""; }; 357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; }; 3D36915A1BDA8CBB007B22D8 /* uie_thumb_big.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = uie_thumb_big.png; path = UIExplorer/Images.xcassets/uie_thumb_big.imageset/uie_thumb_big.png; sourceTree = SOURCE_ROOT; }; 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = ""; }; @@ -498,6 +501,8 @@ 272E6B3A1BEA846C001FCF37 /* NativeExampleViews */ = { isa = PBXGroup; children = ( + 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */, + 27F441EA1BEBE5030039B79C /* FlexibleSizeExampleView.h */, 272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */, 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */, ); @@ -869,6 +874,7 @@ files = ( 272E6B3F1BEA849E001FCF37 /* UpdatePropertiesExampleView.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.h b/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.h new file mode 100644 index 000000000..e4427fec5 --- /dev/null +++ b/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.h @@ -0,0 +1,20 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import +#import "RCTView.h" + +@interface FlexibleSizeExampleView : RCTView + +@end diff --git a/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.m b/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.m new file mode 100644 index 000000000..134d128cf --- /dev/null +++ b/Examples/UIExplorer/UIExplorer/NativeExampleViews/FlexibleSizeExampleView.m @@ -0,0 +1,119 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#import "AppDelegate.h" + +#import "FlexibleSizeExampleView.h" +#import "RCTJavaScriptLoader.h" +#import "RCTBridge.h" +#import "RCTRootView.h" +#import "RCTRootViewDelegate.h" + +#import "RCTViewManager.h" + +@interface FlexibleSizeExampleViewManager : RCTViewManager + +@end + +@implementation FlexibleSizeExampleViewManager + +RCT_EXPORT_MODULE(); + +- (UIView *)view +{ + return [FlexibleSizeExampleView new]; +} + +@end + + +@interface FlexibleSizeExampleView () + +@end + + +@implementation FlexibleSizeExampleView +{ + RCTRootView *_resizableRootView; + UITextView *_currentSizeTextView; + BOOL _sizeUpdated; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _sizeUpdated = NO; + + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + _resizableRootView = [[RCTRootView alloc] initWithBridge:appDelegate.bridge + moduleName:@"RootViewSizeFlexibilityExampleApp" + initialProperties:@{}]; + + [_resizableRootView setSizeFlexibility:RCTRootViewSizeFlexibilityHeight]; + + _currentSizeTextView = [UITextView new]; + _currentSizeTextView.editable = NO; + _currentSizeTextView.text = @"Resizable view has not been resized yet"; + _currentSizeTextView.textColor = [UIColor blackColor]; + _currentSizeTextView.backgroundColor = [UIColor whiteColor]; + _currentSizeTextView.font = [UIFont boldSystemFontOfSize:10]; + + _resizableRootView.delegate = self; + + [self addSubview:_currentSizeTextView]; + [self addSubview:_resizableRootView]; + } + return self; +} + +- (void)layoutSubviews +{ + float textViewHeight = 60; + float spacingHeight = 10; + [_resizableRootView setFrame:CGRectMake(0, textViewHeight + spacingHeight, self.frame.size.width, _resizableRootView.frame.size.height)]; + [_currentSizeTextView setFrame:CGRectMake(0, 0, self.frame.size.width, textViewHeight)]; +} + + +- (NSArray *> *)reactSubviews +{ + // this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy + return @[]; +} + + +#pragma mark - RCTRootViewDelegate + +- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView +{ + CGRect newFrame = rootView.frame; + newFrame.size = rootView.intrinsicSize; + + if (!_sizeUpdated) { + _sizeUpdated = TRUE; + _currentSizeTextView.text = [NSString stringWithFormat:@"RCTRootViewDelegate: content with initially unknown size has appeared, updating root view's size so the content fits."]; + + } else { + _currentSizeTextView.text = [NSString stringWithFormat:@"RCTRootViewDelegate: content size has been changed to (%ld, %ld), updating root view's size.", + (long)newFrame.size.width, + (long)newFrame.size.height]; + + } + + rootView.frame = newFrame; +} + +@end diff --git a/Examples/UIExplorer/UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.m b/Examples/UIExplorer/UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.m index f6852313a..cc78f6cff 100644 --- a/Examples/UIExplorer/UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.m +++ b/Examples/UIExplorer/UIExplorer/NativeExampleViews/UpdatePropertiesExampleView.m @@ -88,6 +88,7 @@ RCT_EXPORT_MODULE(); - (NSArray *> *)reactSubviews { + // this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy return @[]; } diff --git a/Examples/UIExplorer/UIExplorerApp.ios.js b/Examples/UIExplorer/UIExplorerApp.ios.js index b8ea584e6..c8c4a834f 100644 --- a/Examples/UIExplorer/UIExplorerApp.ios.js +++ b/Examples/UIExplorer/UIExplorerApp.ios.js @@ -23,6 +23,7 @@ var { NavigatorIOS, StyleSheet, Text, + TouchableHighlight, View } = React; @@ -72,6 +73,24 @@ var styles = StyleSheet.create({ itemWrapper: { backgroundColor: '#eaeaea', }, + bigContainer: { + flex: 1, + height: 60, + backgroundColor: 'gray', + }, + smallContainer: { + flex: 1, + height: 40, + backgroundColor: 'gray', + }, + center: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + whiteText: { + color: 'white', + } }); var SetPropertiesExampleApp = React.createClass({ @@ -94,7 +113,35 @@ var SetPropertiesExampleApp = React.createClass({ }, }); +var RootViewSizeFlexibilityExampleApp = React.createClass({ + + getInitialState: function () { + return { toggled: false }; + }, + + _onPressButton: function() { + this.setState({ toggled: !this.state.toggled }); + }, + + render: function() { + var viewStyle = this.state.toggled ? styles.bigContainer : styles.smallContainer; + + return ( + + + + + React Native Button + + + + + ); + }, +}); + AppRegistry.registerComponent('SetPropertiesExampleApp', () => SetPropertiesExampleApp); +AppRegistry.registerComponent('RootViewSizeFlexibilityExampleApp', () => RootViewSizeFlexibilityExampleApp); AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp); UIExplorerList.registerComponents();