From 9bbc70c4427b6177bac666fb79d59ca266850684 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Mon, 2 Oct 2017 11:03:00 -0700 Subject: [PATCH] Re-render views when direction changes Summary: This is required for D5874536, wherein I'll be introducing direction-aware props for borders. When a view's border changes due to a direction update, only the frames of its children update. Therefore, only the children `UIView`s get a chance to be re-rendered. This is incorrect because the view that's had its borders changed also needs to re-render. So, I keep a track of the layout direction in a property on all shadow views. Then, when I update that prop within `applyLayoutNode`, I push shadow views into the `viewsWithNewFrames` set. Reviewed By: mmmulani Differential Revision: D5944488 fbshipit-source-id: 3f23e9973f3555612920703cdb6cec38e6360d2d --- Libraries/Text/RCTShadowText.m | 12 +- RNTester/js/TextExample.ios.js | 1041 +++++++++++++--------- React/Modules/RCTUIManager.m | 2 +- React/Views/RCTScrollContentShadowView.m | 2 +- React/Views/RCTShadowView.h | 10 +- React/Views/RCTShadowView.m | 7 +- 6 files changed, 631 insertions(+), 443 deletions(-) diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 00770dea9..fe2b03772 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -38,7 +38,7 @@ static CGFloat const kAutoSizeGranularity = 0.001f; CGFloat _cachedTextStorageWidthMode; NSAttributedString *_cachedAttributedString; CGFloat _effectiveLetterSpacing; - UIUserInterfaceLayoutDirection _cachedEffectiveLayoutDirection; + UIUserInterfaceLayoutDirection _cachedLayoutDirection; } static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode) @@ -72,7 +72,7 @@ static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, f _fontSizeMultiplier = 1.0; _textAlign = NSTextAlignmentNatural; _writingDirection = NSWritingDirectionNatural; - _cachedEffectiveLayoutDirection = UIUserInterfaceLayoutDirectionLeftToRight; + _cachedLayoutDirection = UIUserInterfaceLayoutDirectionLeftToRight; YGNodeSetMeasureFunc(self.yogaNode, RCTMeasure); @@ -198,7 +198,7 @@ static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, f _cachedTextStorage && (width == _cachedTextStorageWidth || (isnan(width) && isnan(_cachedTextStorageWidth))) && widthMode == _cachedTextStorageWidthMode && - _cachedEffectiveLayoutDirection == self.effectiveLayoutDirection + _cachedLayoutDirection == self.layoutDirection ) { return _cachedTextStorage; } @@ -272,12 +272,12 @@ static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, f if ( ![self isTextDirty] && _cachedAttributedString && - _cachedEffectiveLayoutDirection == self.effectiveLayoutDirection + _cachedLayoutDirection == self.layoutDirection ) { return _cachedAttributedString; } - _cachedEffectiveLayoutDirection = self.effectiveLayoutDirection; + _cachedLayoutDirection = self.layoutDirection; if (_fontSize && !isnan(_fontSize)) { fontSize = @(_fontSize); @@ -419,7 +419,7 @@ static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, f // Text alignment NSTextAlignment textAlign = _textAlign; if (textAlign == NSTextAlignmentRight || textAlign == NSTextAlignmentLeft) { - if (_cachedEffectiveLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) { + if (_cachedLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) { if (textAlign == NSTextAlignmentRight) { textAlign = NSTextAlignmentLeft; } else { diff --git a/RNTester/js/TextExample.ios.js b/RNTester/js/TextExample.ios.js index 5e5cee093..9c757896e 100644 --- a/RNTester/js/TextExample.ios.js +++ b/RNTester/js/TextExample.ios.js @@ -7,6 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. * * @flow + * @format * @providesModule TextExample */ 'use strict'; @@ -15,13 +16,56 @@ const Platform = require('Platform'); var React = require('react'); var createReactClass = require('create-react-class'); var ReactNative = require('react-native'); -var { - Image, - StyleSheet, - Text, - View, - LayoutAnimation, -} = ReactNative; +var {Image, Text, View, LayoutAnimation, Button} = ReactNative; + +type TextAlignExampleRTLState = {| + isRTL: boolean, +|}; + +class TextAlignRTLExample extends React.Component<*, TextAlignExampleRTLState> { + constructor(...args: Array<*>) { + super(...args); + + this.state = { + isRTL: false, + }; + } + + render() { + const {isRTL} = this.state; + const toggleRTL = () => this.setState({isRTL: !isRTL}); + return ( + + auto (default) - english LTR + + \u0623\u062D\u0628 \u0627\u0644\u0644\u063A\u0629 + \u0627\u0644\u0639\u0631\u0628\u064A\u0629 auto (default) - arabic RTL + + + left left left left left left left left left left left left left left + left + + + center center center center center center center center center center + center + + + right right right right right right right right right right right + right right + + + justify: this text component{"'"}s contents are laid out with + "textAlign: justify" and as you can see all of the lines except the + last one span the available width of the parent container. + +