diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@2x.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@2x.png new file mode 100644 index 000000000..16a6da742 Binary files /dev/null and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@2x.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@3x.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@3x.png new file mode 100644 index 000000000..1b69b5192 Binary files /dev/null and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10@3x.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10_tvOS.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10_tvOS.png new file mode 100644 index 000000000..4958d3d21 Binary files /dev/null and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1-iOS10_tvOS.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1@2x.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1@2x.png new file mode 100644 index 000000000..6c02ce1fd Binary files /dev/null and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1@2x.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1_tvOS.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1_tvOS.png new file mode 100644 index 000000000..5be05ba37 Binary files /dev/null and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testScrollViewExample_1_tvOS.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerSnapshotTests.m b/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerSnapshotTests.m index f3107791e..eff099f35 100644 --- a/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerSnapshotTests.m +++ b/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerSnapshotTests.m @@ -43,6 +43,7 @@ RCT_TEST(ViewExample) RCT_TEST(LayoutExample) +RCT_TEST(ScrollViewExample) RCT_TEST(TextExample) #if !TARGET_OS_TV // No switch or slider available on tvOS diff --git a/Examples/UIExplorer/js/ScrollViewExample.js b/Examples/UIExplorer/js/ScrollViewExample.js index 4d5dc6bcf..17226919b 100644 --- a/Examples/UIExplorer/js/ScrollViewExample.js +++ b/Examples/UIExplorer/js/ScrollViewExample.js @@ -33,7 +33,7 @@ var { Image } = ReactNative; -exports.displayName = (undefined: ?string); +exports.displayName = 'ScrollViewExample'; exports.title = ''; exports.description = 'Component that enables scrolling through child components'; exports.examples = [ @@ -50,7 +50,7 @@ exports.examples = [ onScroll={() => { console.log('onScroll!'); }} scrollEventThrottle={200} style={styles.scrollView}> - {THUMBS.map(createThumbRow)} + {THUMB_URLS.map(createThumbRow)} (horizontal = true)', description: 'You can display \'s child components horizontally rather than vertically', render: function() { - var _scrollView: ScrollView; + + function renderScrollView(title: string, addtionalStyles: StyleSheet) { + var _scrollView: ScrollView; + return ( + + {title} + { _scrollView = scrollView; }} + automaticallyAdjustContentInsets={false} + horizontal={true} + style={[styles.scrollView, styles.horizontalScrollView]}> + {THUMB_URLS.map(createThumbRow)} + + { _scrollView.scrollTo({x: 0}); }}> + Scroll to start + + { _scrollView.scrollToEnd({animated: true}); }}> + Scroll to end + + + ); + } + return ( - { _scrollView = scrollView; }} - automaticallyAdjustContentInsets={false} - horizontal={true} - style={[styles.scrollView, styles.horizontalScrollView]}> - {THUMBS.map(createThumbRow)} - - { _scrollView.scrollTo({x: 0}); }}> - Scroll to start - - { _scrollView.scrollToEnd({animated: true}); }}> - Scroll to end - + {renderScrollView('LTR layout', {direction: 'ltr'})} + {renderScrollView('RTL layout', {direction: 'rtl'})} ); } @@ -101,49 +112,59 @@ class Thumb extends React.Component { render() { return ( - - + + ); } } -var THUMBS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png']; -THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS -var createThumbRow = (uri, i) => ; +var THUMB_URLS = [ + require('./Thumbnails/like.png'), + require('./Thumbnails/dislike.png'), + require('./Thumbnails/call.png'), + require('./Thumbnails/fist.png'), + require('./Thumbnails/bandaged.png'), + require('./Thumbnails/flowers.png'), + require('./Thumbnails/heart.png'), + require('./Thumbnails/liking.png'), + require('./Thumbnails/party.png'), + require('./Thumbnails/poke.png'), + require('./Thumbnails/superlike.png'), + require('./Thumbnails/victory.png'), +]; + +THUMB_URLS = THUMB_URLS.concat(THUMB_URLS); // double length of THUMB_URLS + +var createThumbRow = (uri, i) => ; var styles = StyleSheet.create({ scrollView: { - backgroundColor: '#6A85B1', + backgroundColor: '#eeeeee', height: 300, }, horizontalScrollView: { - height: 120, - }, - containerPage: { - height: 50, - width: 50, - backgroundColor: '#527FE4', - padding: 5, + height: 106, }, text: { - fontSize: 20, - color: '#888888', - left: 80, - top: 20, - height: 40, + fontSize: 16, + fontWeight: 'bold', + margin: 5, + textAlign: 'left', }, button: { - margin: 7, + margin: 5, padding: 5, alignItems: 'center', - backgroundColor: '#eaeaea', + backgroundColor: '#cccccc', borderRadius: 3, }, - buttonContents: { - flexDirection: 'row', - width: 64, - height: 64, + thumb: { + margin: 5, + padding: 5, + backgroundColor: '#cccccc', + borderRadius: 3, + minWidth: 96, }, img: { width: 64, diff --git a/Libraries/StyleSheet/LayoutPropTypes.js b/Libraries/StyleSheet/LayoutPropTypes.js index 206943412..1d6df3440 100644 --- a/Libraries/StyleSheet/LayoutPropTypes.js +++ b/Libraries/StyleSheet/LayoutPropTypes.js @@ -470,6 +470,18 @@ var LayoutPropTypes = { * more details. */ zIndex: ReactPropTypes.number, + + /** `direction` specifies the directional flow of the user interface. + * The default is `inherit`, except for root node which will have + * value based on the current locale. + * See https://facebook.github.io/yoga/docs/rtl/ + * for more details. + */ + direction: ReactPropTypes.oneOf([ + 'inherit', + 'ltr', + 'rtl', + ]), }; module.exports = LayoutPropTypes; diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 18c2a157b..57e8333df 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -118,6 +118,7 @@ typedef BOOL css_backface_visibility_t; + (YGAlign)YGAlign:(id)json; + (YGPositionType)YGPositionType:(id)json; + (YGWrap)YGWrap:(id)json; ++ (YGDirection)YGDirection:(id)json; + (RCTPointerEvents)RCTPointerEvents:(id)json; + (RCTAnimationType)RCTAnimationType:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index e26026440..4d842904e 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -667,6 +667,12 @@ RCT_ENUM_CONVERTER(YGAlign, (@{ @"baseline": @(YGAlignBaseline) }), YGAlignFlexStart, intValue) +RCT_ENUM_CONVERTER(YGDirection, (@{ + @"inherit": @(YGDirectionInherit), + @"ltr": @(YGDirectionLTR), + @"rtl": @(YGDirectionRTL), +}), YGDirectionInherit, intValue) + RCT_ENUM_CONVERTER(YGPositionType, (@{ @"absolute": @(YGPositionTypeAbsolute), @"relative": @(YGPositionTypeRelative) diff --git a/React/Views/RCTRootShadowView.m b/React/Views/RCTRootShadowView.m index 96fc0c1cc..70fb827b9 100644 --- a/React/Views/RCTRootShadowView.m +++ b/React/Views/RCTRootShadowView.m @@ -7,9 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "RCTI18nUtil.h" #import "RCTRootShadowView.h" +#import "RCTI18nUtil.h" + @implementation RCTRootShadowView /** @@ -20,9 +21,7 @@ { self = [super init]; if (self) { - if ([[RCTI18nUtil sharedInstance] isRTL]) { - YGNodeStyleSetDirection(self.cssNode, YGDirectionRTL); - } + self.direction = [[RCTI18nUtil sharedInstance] isRTL] ? YGDirectionRTL : YGDirectionLTR; } return self; } diff --git a/React/Views/RCTShadowView.h b/React/Views/RCTShadowView.h index fc51df83a..c2e8ef640 100644 --- a/React/Views/RCTShadowView.h +++ b/React/Views/RCTShadowView.h @@ -146,6 +146,11 @@ typedef void (^RCTApplierBlock)(NSDictionary *viewRegistry */ @property (nonatomic, assign) NSInteger zIndex; +/** + * Interface direction (LTR or RTL) + */ +@property (nonatomic, assign) YGDirection direction; + /** * Clipping properties */ diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index d300d1ba7..da9a8a83a 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -665,6 +665,7 @@ RCT_STYLE_PROPERTY(AlignItems, alignItems, AlignItems, YGAlign) RCT_STYLE_PROPERTY(Position, position, PositionType, YGPositionType) RCT_STYLE_PROPERTY(FlexWrap, flexWrap, FlexWrap, YGWrap) RCT_STYLE_PROPERTY(Overflow, overflow, Overflow, YGOverflow) +RCT_STYLE_PROPERTY(Direction, direction, Direction, YGDirection) RCT_STYLE_PROPERTY(AspectRatio, aspectRatio, AspectRatio, float) - (void)setBackgroundColor:(UIColor *)color diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index cbecf8c13..30143b385 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -317,5 +317,6 @@ RCT_EXPORT_SHADOW_PROPERTY(overflow, YGOverflow) RCT_EXPORT_SHADOW_PROPERTY(onLayout, RCTDirectEventBlock) RCT_EXPORT_SHADOW_PROPERTY(zIndex, NSInteger) +RCT_EXPORT_SHADOW_PROPERTY(direction, YGDirection) @end