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
This commit is contained in:
parent
53a339a459
commit
9bbc70c442
|
@ -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 {
|
||||
|
|
|
@ -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 (
|
||||
<View style={{direction: isRTL ? 'rtl' : 'ltr'}}>
|
||||
<Text>auto (default) - english LTR</Text>
|
||||
<Text>
|
||||
\u0623\u062D\u0628 \u0627\u0644\u0644\u063A\u0629
|
||||
\u0627\u0644\u0639\u0631\u0628\u064A\u0629 auto (default) - arabic RTL
|
||||
</Text>
|
||||
<Text style={{textAlign: 'left'}}>
|
||||
left left left left left left left left left left left left left left
|
||||
left
|
||||
</Text>
|
||||
<Text style={{textAlign: 'center'}}>
|
||||
center center center center center center center center center center
|
||||
center
|
||||
</Text>
|
||||
<Text style={{textAlign: 'right'}}>
|
||||
right right right right right right right right right right right
|
||||
right right
|
||||
</Text>
|
||||
<Text style={{textAlign: 'justify'}}>
|
||||
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.
|
||||
</Text>
|
||||
<Button
|
||||
onPress={toggleRTL}
|
||||
title={`Switch to ${isRTL ? 'LTR' : 'RTL'}`}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Entity extends React.Component<$FlowFixMeProps> {
|
||||
render() {
|
||||
|
@ -38,25 +82,31 @@ class AttributeToggler extends React.Component<{}, $FlowFixMeState> {
|
|||
|
||||
toggleWeight = () => {
|
||||
this.setState({
|
||||
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
|
||||
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold',
|
||||
});
|
||||
};
|
||||
|
||||
increaseSize = () => {
|
||||
this.setState({
|
||||
fontSize: this.state.fontSize + 1
|
||||
fontSize: this.state.fontSize + 1,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
var curStyle = {fontWeight: this.state.fontWeight, fontSize: this.state.fontSize};
|
||||
var curStyle = {
|
||||
fontWeight: this.state.fontWeight,
|
||||
fontSize: this.state.fontSize,
|
||||
};
|
||||
return (
|
||||
<View>
|
||||
<Text style={curStyle}>
|
||||
Tap the controls below to change attributes.
|
||||
</Text>
|
||||
<Text>
|
||||
<Text>See how it will even work on <Text style={curStyle}>this nested text</Text></Text>
|
||||
<Text>
|
||||
See how it will even work on{' '}
|
||||
<Text style={curStyle}>this nested text</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
<Text
|
||||
style={{backgroundColor: '#ffaaaa', marginTop: 5}}
|
||||
|
@ -76,7 +126,7 @@ class AttributeToggler extends React.Component<{}, $FlowFixMeState> {
|
|||
var AdjustingFontSize = createReactClass({
|
||||
displayName: 'AdjustingFontSize',
|
||||
getInitialState: function() {
|
||||
return {dynamicText:'', shouldRender: true,};
|
||||
return {dynamicText: '', shouldRender: true};
|
||||
},
|
||||
reset: function() {
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
|
@ -93,37 +143,58 @@ var AdjustingFontSize = createReactClass({
|
|||
},
|
||||
addText: function() {
|
||||
this.setState({
|
||||
dynamicText: this.state.dynamicText + (Math.floor((Math.random() * 10) % 2) ? ' foo' : ' bar'),
|
||||
dynamicText:
|
||||
this.state.dynamicText +
|
||||
(Math.floor((Math.random() * 10) % 2) ? ' foo' : ' bar'),
|
||||
});
|
||||
},
|
||||
removeText: function() {
|
||||
this.setState({
|
||||
dynamicText: this.state.dynamicText.slice(0, this.state.dynamicText.length - 4),
|
||||
dynamicText: this.state.dynamicText.slice(
|
||||
0,
|
||||
this.state.dynamicText.length - 4,
|
||||
),
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
|
||||
if (!this.state.shouldRender) {
|
||||
return (<View/>);
|
||||
return <View />;
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<Text ellipsizeMode="tail" numberOfLines={1} style={{fontSize: 36, marginVertical: 6}}>
|
||||
<Text
|
||||
ellipsizeMode="tail"
|
||||
numberOfLines={1}
|
||||
style={{fontSize: 36, marginVertical: 6}}>
|
||||
Truncated text is baaaaad.
|
||||
</Text>
|
||||
<Text numberOfLines={1} adjustsFontSizeToFit={true} style={{fontSize: 40, marginVertical:6}}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
adjustsFontSizeToFit={true}
|
||||
style={{fontSize: 40, marginVertical: 6}}>
|
||||
Shrinking to fit available space is much better!
|
||||
</Text>
|
||||
|
||||
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={{fontSize:30, marginVertical:6}}>
|
||||
<Text
|
||||
adjustsFontSizeToFit={true}
|
||||
numberOfLines={1}
|
||||
style={{fontSize: 30, marginVertical: 6}}>
|
||||
{'Add text to me to watch me shrink!' + ' ' + this.state.dynamicText}
|
||||
</Text>
|
||||
|
||||
<Text adjustsFontSizeToFit={true} numberOfLines={4} style={{fontSize:20, marginVertical:6}}>
|
||||
{'Multiline text component shrinking is supported, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' + ' ' + this.state.dynamicText}
|
||||
<Text
|
||||
adjustsFontSizeToFit={true}
|
||||
numberOfLines={4}
|
||||
style={{fontSize: 20, marginVertical: 6}}>
|
||||
{'Multiline text component shrinking is supported, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
|
||||
' ' +
|
||||
this.state.dynamicText}
|
||||
</Text>
|
||||
|
||||
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={{marginVertical:6}}>
|
||||
<Text
|
||||
adjustsFontSizeToFit={true}
|
||||
numberOfLines={1}
|
||||
style={{marginVertical: 6}}>
|
||||
<Text style={{fontSize: 14}}>
|
||||
{'Differently sized nested elements will shrink together. '}
|
||||
</Text>
|
||||
|
@ -132,26 +203,26 @@ var AdjustingFontSize = createReactClass({
|
|||
</Text>
|
||||
</Text>
|
||||
|
||||
<View style={{flexDirection:'row', justifyContent:'space-around', marginTop: 5, marginVertical:6}}>
|
||||
<Text
|
||||
style={{backgroundColor: '#ffaaaa'}}
|
||||
onPress={this.reset}>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
marginTop: 5,
|
||||
marginVertical: 6,
|
||||
}}>
|
||||
<Text style={{backgroundColor: '#ffaaaa'}} onPress={this.reset}>
|
||||
Reset
|
||||
</Text>
|
||||
<Text
|
||||
style={{backgroundColor: '#aaaaff'}}
|
||||
onPress={this.removeText}>
|
||||
<Text style={{backgroundColor: '#aaaaff'}} onPress={this.removeText}>
|
||||
Remove Text
|
||||
</Text>
|
||||
<Text
|
||||
style={{backgroundColor: '#aaffaa'}}
|
||||
onPress={this.addText}>
|
||||
<Text style={{backgroundColor: '#aaffaa'}} onPress={this.addText}>
|
||||
Add Text
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<Text>';
|
||||
|
@ -163,12 +234,13 @@ exports.examples = [
|
|||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
The text should wrap if it goes on multiple lines. See, this is going to
|
||||
the next line.
|
||||
The text should wrap if it goes on multiple lines. See, this is going
|
||||
to the next line.
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Padding',
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -177,61 +249,63 @@ exports.examples = [
|
|||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Font Family',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Times' : 'Cochin')}}>
|
||||
<Text style={{fontFamily: Platform.isTVOS ? 'Times' : 'Cochin'}}>
|
||||
Cochin
|
||||
</Text>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Times' : 'Cochin'), fontWeight: 'bold'}}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: Platform.isTVOS ? 'Times' : 'Cochin',
|
||||
fontWeight: 'bold',
|
||||
}}>
|
||||
Cochin bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Helvetica'}}>
|
||||
Helvetica
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Helvetica'}}>Helvetica</Text>
|
||||
<Text style={{fontFamily: 'Helvetica', fontWeight: 'bold'}}>
|
||||
Helvetica bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Courier' : 'Verdana')}}>
|
||||
<Text style={{fontFamily: Platform.isTVOS ? 'Courier' : 'Verdana'}}>
|
||||
Verdana
|
||||
</Text>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Courier' : 'Verdana'), fontWeight: 'bold'}}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: Platform.isTVOS ? 'Courier' : 'Verdana',
|
||||
fontWeight: 'bold',
|
||||
}}>
|
||||
Verdana bold
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Font Size',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontSize: 23}}>
|
||||
Size 23
|
||||
</Text>
|
||||
<Text style={{fontSize: 8}}>
|
||||
Size 8
|
||||
</Text>
|
||||
<Text style={{fontSize: 23}}>Size 23</Text>
|
||||
<Text style={{fontSize: 8}}>Size 8</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Color',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{color: 'red'}}>
|
||||
Red color
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
Blue color
|
||||
</Text>
|
||||
<Text style={{color: 'red'}}>Red color</Text>
|
||||
<Text style={{color: 'blue'}}>Blue color</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Font Weight',
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -254,61 +328,97 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Font Style',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontStyle: 'normal'}}>
|
||||
Normal text
|
||||
</Text>
|
||||
<Text style={{fontStyle: 'italic'}}>
|
||||
Italic text
|
||||
</Text>
|
||||
<Text style={{fontStyle: 'normal'}}>Normal text</Text>
|
||||
<Text style={{fontStyle: 'italic'}}>Italic text</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Selectable',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text selectable={true}>
|
||||
This text is <Text style={{fontWeight: 'bold'}}>selectable</Text> if you click-and-hold.
|
||||
This text is <Text style={{fontWeight: 'bold'}}>selectable</Text> if
|
||||
you click-and-hold.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Text Decoration',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{textDecorationLine: 'underline', textDecorationStyle: 'solid'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'solid',
|
||||
}}>
|
||||
Solid underline
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'underline', textDecorationStyle: 'double', textDecorationColor: '#ff0000'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'double',
|
||||
textDecorationColor: '#ff0000',
|
||||
}}>
|
||||
Double underline with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'underline', textDecorationStyle: 'dashed', textDecorationColor: '#9CDC40'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'dashed',
|
||||
textDecorationColor: '#9CDC40',
|
||||
}}>
|
||||
Dashed underline with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'underline', textDecorationStyle: 'dotted', textDecorationColor: 'blue'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'underline',
|
||||
textDecorationStyle: 'dotted',
|
||||
textDecorationColor: 'blue',
|
||||
}}>
|
||||
Dotted underline with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'none'}}>
|
||||
None textDecoration
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'line-through', textDecorationStyle: 'solid'}}>
|
||||
<Text style={{textDecorationLine: 'none'}}>None textDecoration</Text>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'solid',
|
||||
}}>
|
||||
Solid line-through
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'line-through', textDecorationStyle: 'double', textDecorationColor: '#ff0000'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'double',
|
||||
textDecorationColor: '#ff0000',
|
||||
}}>
|
||||
Double line-through with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'line-through', textDecorationStyle: 'dashed', textDecorationColor: '#9CDC40'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'dashed',
|
||||
textDecorationColor: '#9CDC40',
|
||||
}}>
|
||||
Dashed line-through with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'line-through', textDecorationStyle: 'dotted', textDecorationColor: 'blue'}}>
|
||||
<Text
|
||||
style={{
|
||||
textDecorationLine: 'line-through',
|
||||
textDecorationStyle: 'dotted',
|
||||
textDecorationColor: 'blue',
|
||||
}}>
|
||||
Dotted line-through with custom color
|
||||
</Text>
|
||||
<Text style={{textDecorationLine: 'underline line-through'}}>
|
||||
|
@ -317,9 +427,11 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Nested',
|
||||
description: 'Nested text components will inherit the styles of their ' +
|
||||
description:
|
||||
'Nested text components will inherit the styles of their ' +
|
||||
'parents (only backgroundColor is inherited from non-Text parents). ' +
|
||||
'<Text> only supports other <Text> and raw text (strings) as children.',
|
||||
render: function() {
|
||||
|
@ -357,42 +469,51 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Text Align',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>auto (default) - english LTR</Text>
|
||||
<Text>
|
||||
auto (default) - english LTR
|
||||
</Text>
|
||||
<Text>
|
||||
أحب اللغة العربية auto (default) - arabic RTL
|
||||
\u0623\u062D\u0628 \u0627\u0644\u0644\u063A\u0629
|
||||
\u0627\u0644\u0639\u0631\u0628\u064A\u0629 auto (default) - arabic
|
||||
RTL
|
||||
</Text>
|
||||
<Text style={{textAlign: 'left'}}>
|
||||
left left left left left left left left left left left left left left left
|
||||
left left left left left left left left left left left left left
|
||||
left left
|
||||
</Text>
|
||||
<Text style={{textAlign: 'center'}}>
|
||||
center center center center center center center center center center center
|
||||
center center center center center center center center center
|
||||
center center
|
||||
</Text>
|
||||
<Text style={{textAlign: 'right'}}>
|
||||
right right right right right right right right right right right right right
|
||||
right right right right right right right right right right right
|
||||
right right
|
||||
</Text>
|
||||
<Text style={{textAlign: 'justify'}}>
|
||||
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.
|
||||
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.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Text Align with RTL',
|
||||
render: function() {
|
||||
return <TextAlignRTLExample />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Letter Spacing',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{letterSpacing: 0}}>
|
||||
letterSpacing = 0
|
||||
</Text>
|
||||
<Text style={{letterSpacing: 0}}>letterSpacing = 0</Text>
|
||||
<Text style={{letterSpacing: 2, marginTop: 5}}>
|
||||
letterSpacing = 2
|
||||
</Text>
|
||||
|
@ -405,16 +526,18 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Spaces',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
A {'generated'} {' '} {'string'} and some spaces
|
||||
A {'generated'} {'string'} and some spaces
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Line Height',
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -426,20 +549,21 @@ exports.examples = [
|
|||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Empty Text',
|
||||
description: 'It\'s ok to have Text with zero or null children.',
|
||||
render: function() {
|
||||
return (
|
||||
<Text />
|
||||
);
|
||||
},
|
||||
}, {
|
||||
{
|
||||
title: 'Empty Text',
|
||||
description: "It's ok to have Text with zero or null children.",
|
||||
render: function() {
|
||||
return <Text />;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Toggling Attributes',
|
||||
render: function(): React.Element<any> {
|
||||
return <AttributeToggler />;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'backgroundColor attribute',
|
||||
description: 'backgroundColor is inherited from all types of views.',
|
||||
render: function() {
|
||||
|
@ -447,13 +571,17 @@ exports.examples = [
|
|||
<Text style={{backgroundColor: 'yellow'}}>
|
||||
Yellow container background,
|
||||
<Text style={{backgroundColor: '#ffaaaa'}}>
|
||||
{' '}red background,
|
||||
{' '}
|
||||
red background,
|
||||
<Text style={{backgroundColor: '#aaaaff'}}>
|
||||
{' '}blue background,
|
||||
{' '}
|
||||
blue background,
|
||||
<Text>
|
||||
{' '}inherited blue background,
|
||||
{' '}
|
||||
inherited blue background,
|
||||
<Text style={{backgroundColor: '#aaffaa'}}>
|
||||
{' '}nested green background.
|
||||
{' '}
|
||||
nested green background.
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
|
@ -461,44 +589,70 @@ exports.examples = [
|
|||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'numberOfLines attribute',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text numberOfLines={1}>
|
||||
Maximum of one line, no matter how much I write here. If I keep writing, it{"'"}ll just truncate after one line.
|
||||
Maximum of one line, no matter how much I write here. If I keep
|
||||
writing, it{"'"}ll just truncate after one line.
|
||||
</Text>
|
||||
<Text numberOfLines={2} style={{marginTop: 20}}>
|
||||
Maximum of two lines, no matter how much I write here. If I keep writing, it{"'"}ll just truncate after two lines.
|
||||
Maximum of two lines, no matter how much I write here. If I keep
|
||||
writing, it{"'"}ll just truncate after two lines.
|
||||
</Text>
|
||||
<Text style={{marginTop: 20}}>
|
||||
No maximum lines specified, no matter how much I write here. If I keep writing, it{"'"}ll just keep going and going.
|
||||
No maximum lines specified, no matter how much I write here. If I
|
||||
keep writing, it{"'"}ll just keep going and going.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Text highlighting (tap the link to see highlight)',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>Lorem ipsum dolor sit amet, <Text suppressHighlighting={false} style={{backgroundColor: 'white', textDecorationLine: 'underline', color: 'blue'}} onPress={() => null}>consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud</Text> exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</Text>
|
||||
<Text>
|
||||
Lorem ipsum dolor sit amet,{' '}
|
||||
<Text
|
||||
suppressHighlighting={false}
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
textDecorationLine: 'underline',
|
||||
color: 'blue',
|
||||
}}
|
||||
onPress={() => null}>
|
||||
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
|
||||
labore et dolore magna aliqua. Ut enim ad minim veniam, quis
|
||||
nostrud
|
||||
</Text>{' '}
|
||||
exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'allowFontScaling attribute',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
By default, text will respect Text Size accessibility setting on iOS.
|
||||
It means that all font sizes will be increased or descreased depending on the value of Text Size setting in
|
||||
{" "}<Text style={{fontWeight: 'bold'}}>Settings.app - Display & Brightness - Text Size</Text>
|
||||
By default, text will respect Text Size accessibility setting on
|
||||
iOS. It means that all font sizes will be increased or descreased
|
||||
depending on the value of Text Size setting in{' '}
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
Settings.app - Display & Brightness - Text Size
|
||||
</Text>
|
||||
</Text>
|
||||
<Text style={{marginTop: 10}}>
|
||||
You can disable scaling for your Text component by passing {"\""}allowFontScaling={"{"}false{"}\""} prop.
|
||||
You can disable scaling for your Text component by passing {'"'}allowFontScaling={'{'}false{'}"'}{' '}
|
||||
prop.
|
||||
</Text>
|
||||
<Text allowFontScaling={false} style={{marginTop: 20}}>
|
||||
This text will not scale.
|
||||
|
@ -506,30 +660,46 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Inline views',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
This text contains an inline blue view <View style={{width: 25, height: 25, backgroundColor: 'steelblue'}} /> and
|
||||
an inline image <Image source={require('./flux.png')} style={{width: 30, height: 11, resizeMode: 'cover'}}/>. Neat, huh?
|
||||
This text contains an inline blue view{' '}
|
||||
<View
|
||||
style={{width: 25, height: 25, backgroundColor: 'steelblue'}}
|
||||
/>{' '}
|
||||
and an inline image{' '}
|
||||
<Image
|
||||
source={require('./flux.png')}
|
||||
style={{width: 30, height: 11, resizeMode: 'cover'}}
|
||||
/>. Neat, huh?
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Text shadow',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontSize: 20, textShadowOffset: {width: 2, height: 2}, textShadowRadius: 1, textShadowColor: '#00cccc'}}>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
textShadowOffset: {width: 2, height: 2},
|
||||
textShadowRadius: 1,
|
||||
textShadowColor: '#00cccc',
|
||||
}}>
|
||||
Demo text shadow
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Ellipsize mode',
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -549,18 +719,25 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Font variants',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontVariant: ['small-caps']}}>
|
||||
Small Caps{'\n'}
|
||||
</Text>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Times' : 'Hoefler Text'), fontVariant: ['oldstyle-nums']}}>
|
||||
<Text style={{fontVariant: ['small-caps']}}>Small Caps{'\n'}</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: Platform.isTVOS ? 'Times' : 'Hoefler Text',
|
||||
fontVariant: ['oldstyle-nums'],
|
||||
}}>
|
||||
Old Style nums 0123456789{'\n'}
|
||||
</Text>
|
||||
<Text style={{fontFamily: (Platform.isTVOS ? 'Times' : 'Hoefler Text'), fontVariant: ['lining-nums']}}>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: Platform.isTVOS ? 'Times' : 'Hoefler Text',
|
||||
fontVariant: ['lining-nums'],
|
||||
}}>
|
||||
Lining nums 0123456789{'\n'}
|
||||
</Text>
|
||||
<Text style={{fontVariant: ['tabular-nums']}}>
|
||||
|
@ -576,9 +753,11 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: 'Dynamic Font Size Adjustment',
|
||||
render: function(): React.Element<any> {
|
||||
return <AdjustingFontSize />;
|
||||
},
|
||||
}];
|
||||
},
|
||||
];
|
||||
|
|
|
@ -494,7 +494,7 @@ static NSDictionary *deviceOrientationEventBody(UIDeviceOrientation orientation)
|
|||
reactTags[index] = shadowView.reactTag;
|
||||
frameDataArray[index++] = (RCTFrameData){
|
||||
shadowView.frame,
|
||||
shadowView.effectiveLayoutDirection,
|
||||
shadowView.layoutDirection,
|
||||
shadowView.isNewView,
|
||||
shadowView.superview.isNewView,
|
||||
shadowView.isHidden,
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
absolutePosition:(CGPoint)absolutePosition
|
||||
{
|
||||
// Call super method if LTR layout is enforced.
|
||||
if (self.effectiveLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight) {
|
||||
if (self.layoutDirection == UIUserInterfaceLayoutDirectionLeftToRight) {
|
||||
[super applyLayoutNode:node
|
||||
viewsWithNewFrame:viewsWithNewFrame
|
||||
absolutePosition:absolutePosition];
|
||||
|
|
|
@ -84,9 +84,10 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
@property (nonatomic, assign, getter=isHidden) BOOL hidden;
|
||||
|
||||
/**
|
||||
* Computed layout direction for the view backed to Yoga node value.
|
||||
* Layout direction for the view as computed in applyLayoutNode.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) UIUserInterfaceLayoutDirection effectiveLayoutDirection;
|
||||
|
||||
@property (nonatomic, assign, readonly) UIUserInterfaceLayoutDirection layoutDirection;
|
||||
|
||||
/**
|
||||
* Position and dimensions.
|
||||
|
@ -187,6 +188,11 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
|
|||
*/
|
||||
@property (nonatomic, assign) CGSize intrinsicContentSize;
|
||||
|
||||
/**
|
||||
* Return the layout direction stored in the Yoga node that backs this view.
|
||||
*/
|
||||
- (UIUserInterfaceLayoutDirection)getLayoutDirectionFromYogaNode;
|
||||
|
||||
/**
|
||||
* Calculate property changes that need to be propagated to the view.
|
||||
* The applierBlocks set contains RCTApplierBlock functions that must be applied
|
||||
|
|
|
@ -204,8 +204,11 @@ static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT],
|
|||
RCTRoundPixelValue(absoluteBottomRight.y - absoluteTopLeft.y)
|
||||
}};
|
||||
|
||||
if (!CGRectEqualToRect(frame, _frame)) {
|
||||
UIUserInterfaceLayoutDirection updatedLayoutDirection = [self getLayoutDirectionFromYogaNode];
|
||||
|
||||
if (!CGRectEqualToRect(frame, _frame) || _layoutDirection != updatedLayoutDirection) {
|
||||
_frame = frame;
|
||||
_layoutDirection = updatedLayoutDirection;
|
||||
[viewsWithNewFrame addObject:self];
|
||||
}
|
||||
|
||||
|
@ -493,7 +496,7 @@ static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT],
|
|||
|
||||
// Layout Direction
|
||||
|
||||
- (UIUserInterfaceLayoutDirection)effectiveLayoutDirection {
|
||||
- (UIUserInterfaceLayoutDirection)getLayoutDirectionFromYogaNode {
|
||||
// Even if `YGNodeLayoutGetDirection` can return `YGDirectionInherit` here, it actually means
|
||||
// that Yoga will use LTR layout for the view (even if layout process is not finished yet).
|
||||
return YGNodeLayoutGetDirection(_yogaNode) == YGDirectionRTL ? UIUserInterfaceLayoutDirectionRightToLeft : UIUserInterfaceLayoutDirectionLeftToRight;
|
||||
|
|
Loading…
Reference in New Issue