Skip to content

Commit

Permalink
The New <Text> on iOS
Browse files Browse the repository at this point in the history
Summary:
This is a complete rewrite of RCTText, the part of React Native which manages Text and TextInput components.

Key points:

* It's understandable now. It follows a simple architectural pattern, and it's easy to debug and iterate. Text flow layout is a first-class citizen in React Native layout system now, not just a wired special case. It also brings entirely new possibilities such as nested interleaving <Text> and <View> components.
* All <Text>-specific APIs were removed from UIManager and co (it's about ~16 public methods which were used exclusively only by <Text>).
* It relies on new Yoga measurement/cloning API and on-dirty handler. So, it removes built-in dirty propagation subsystem from RN completely.
* It caches string fragments properly and granularly on a per-node basis which makes updating text-containing components more performant.
* It does not instantiate UIView for virtual components which reduces memory utilization.
* It drastically improves <TextInput> capabilities (e.g. rich text inside single line <TextInput> is now supported).

Screenshots:
https://cl.ly/2j3r1V0L0324
https://cl.ly/3N2V3C3d3q3R

Reviewed By: mmmulani

Differential Revision: D6617326

fbshipit-source-id: 35d4d81b35c9870e9557d0211c0e934e6072a41e
  • Loading branch information
shergin authored and facebook-github-bot committed Jan 24, 2018
1 parent a975e16 commit 03cab5d
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 12 deletions.
33 changes: 21 additions & 12 deletions js/TextExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,8 @@ exports.examples = [
render: function() {
return (
<Text>
The text
<View style={{borderColor: 'red', borderWidth: 1}}>
<Text style={{borderColor: 'blue', borderWidth: 1}}>Text Inside</Text>
<Text style={{borderColor: 'green', borderWidth: 1}}>Another text Inside</Text>
<Text style={{borderColor: 'yellow', borderWidth: 1}}>
Total inseption
<View style={{borderColor: 'red', borderWidth: 1}}>
<Text style={{borderColor: 'blue', borderWidth: 1}}>Insepted Text Inside</Text>
</View>
</Text>
</View>
The text should wrap if it goes on multiple lines. See, this is going
to the next line.
The text after.
</Text>
);
},
Expand Down Expand Up @@ -759,6 +747,27 @@ exports.examples = [
);
},
},
{
title: 'Nested content',
render: function() {
return (
<Text>
This text has a view
<View style={{borderColor: 'red', borderWidth: 1}}>
<Text style={{borderColor: 'blue', borderWidth: 1}}>which has</Text>
<Text style={{borderColor: 'green', borderWidth: 1}}>another text inside.</Text>
<Text style={{borderColor: 'yellow', borderWidth: 1}}>
And moreover, it has another view
<View style={{borderColor: 'red', borderWidth: 1}}>
<Text style={{borderColor: 'blue', borderWidth: 1}}>with another text inside!</Text>
</View>
</Text>
</View>
Because we need to go deeper.
</Text>
);
},
},
{
title: 'Dynamic Font Size Adjustment',
render: function(): React.Element<any> {
Expand Down
108 changes: 108 additions & 0 deletions js/TextInputExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ var {
TextInput,
View,
StyleSheet,
Slider,
Switch,
} = ReactNative;

class WithLabel extends React.Component<$FlowFixMeProps> {
Expand Down Expand Up @@ -335,6 +337,61 @@ class SelectionExample extends React.Component<$FlowFixMeProps, SelectionExample
}
}

class AutogrowingTextInputExample extends React.Component<$FlowFixMeProps, $FlowFixMeState> {
constructor(props) {
super(props);

this.state = {
width: 100,
multiline: true,
text: '',
contentSize: {
width: 0,
height: 0,
},
};
}

componentWillReceiveProps(props) {
this.setState({
multiline: props.multiline,
});
}

render() {
var {style, multiline, ...props} = this.props;
return (
<View>
<Text>Width:</Text>
<Slider
value={100}
minimumValue={0}
maximumValue={100}
step={10}
onValueChange={(value) => this.setState({width: value})}
/>
<Text>Multiline:</Text>
<Switch
value={this.state.multiline}
onValueChange={(value) => this.setState({multiline: value})}
/>
<Text>TextInput:</Text>
<TextInput
value="prop"
multiline={this.state.multiline}
style={[style, {width: this.state.width + '%'}]}
onChangeText={(value) => this.setState({text: value})}
onContentSizeChange={(event) => this.setState({contentSize: event.nativeEvent.contentSize})}
{...props}
/>
<Text>Plain text value representation:</Text>
<Text>{this.state.text}</Text>
<Text>Content Size: {JSON.stringify(this.state.contentSize)}</Text>
</View>
);
}
}

var styles = StyleSheet.create({
page: {
paddingBottom: 300,
Expand Down Expand Up @@ -478,6 +535,29 @@ exports.examples = [
);
}
},
{
title: 'Nested content and `value` property',
render: function() {
return (
<View>
<WithLabel label="singleline">
<TextInput style={styles.default} value="(value property)">
(first raw text node)
<Text color="red">(internal raw text node)</Text>
(last raw text node)
</TextInput>
</WithLabel>
<WithLabel label="multiline">
<TextInput style={styles.default} multiline={true} value="(value property)">
(first raw text node)
<Text color="red">(internal raw text node)</Text>
(last raw text node)
</TextInput>
</WithLabel>
</View>
);
}
},
{
title: 'Keyboard types',
render: function() {
Expand Down Expand Up @@ -854,6 +934,34 @@ exports.examples = [
);
}
},
{
title: 'Auto-expanding',
render: function() {
return (
<View>
<AutogrowingTextInputExample
enablesReturnKeyAutomatically={true}
returnKeyType="done"
multiline={true}
style={{maxHeight: 400, minHeight: 20, paddingTop: 0, backgroundColor: '#eeeeee', color: 'blue'}}
>
<Text style={{fontSize: 30, color: 'green'}}>
huge
</Text>
generic generic generic
<Text style={{fontSize: 6, color: 'red'}}>
small small small small small small
</Text>
<Text>regular regular</Text>
<Text style={{fontSize: 30, color: 'green'}}>
huge huge huge huge huge
</Text>
generic generic generic
</AutogrowingTextInputExample>
</View>
);
}
},
{
title: 'Attributed text',
render: function() {
Expand Down

0 comments on commit 03cab5d

Please sign in to comment.