Skip to content

Commit 3b9cc0d

Browse files
authored
Merge pull request #26 from taskrabbit/auto_scale_text
Auto scale text in navigation title
2 parents 3e44bc5 + f815f3d commit 3b9cc0d

File tree

3 files changed

+125
-10
lines changed

3 files changed

+125
-10
lines changed

App/Components/AutoScaleText.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React from 'react';
2+
3+
import ReactNative, {
4+
NativeModules,
5+
} from 'react-native';
6+
7+
const UIManager = NativeModules.UIManager;
8+
9+
import Text from './Text';
10+
11+
class AutoScaleText extends React.Component {
12+
static propTypes = {
13+
...Text.propTypes,
14+
maxFontSize: React.PropTypes.number.isRequired,
15+
maxHeight: React.PropTypes.number.isRequired,
16+
color: React.PropTypes.string,
17+
style: React.PropTypes.oneOfType([
18+
Text.propTypes.style,
19+
React.PropTypes.shape({
20+
width: React.PropTypes.number,
21+
}),
22+
]).isRequired,
23+
};
24+
25+
static defaultProps = {
26+
color: 'black',
27+
};
28+
29+
constructor(props) {
30+
super(props);
31+
32+
this.state = {
33+
fontSize: props.maxFontSize,
34+
finished: false,
35+
};
36+
37+
this.visible = true;
38+
}
39+
40+
determineFontSize = () => {
41+
UIManager.measure(ReactNative.findNodeHandle(this.refs.textView), (x, y, w, h, px, py) => {
42+
if (!this.visible) return;
43+
44+
if (h > this.props.maxHeight) {
45+
this.setState({
46+
fontSize: this.state.fontSize - 0.5,
47+
});
48+
this.determineFontSize();
49+
}
50+
else {
51+
this.setState({finished: true});
52+
}
53+
});
54+
};
55+
56+
componentWillUnmount() {
57+
this.visible = false;
58+
}
59+
60+
render() {
61+
return (
62+
<Text
63+
ref='textView'
64+
onLayout={this.determineFontSize}
65+
{...this.props}
66+
style={[
67+
this.props.style,
68+
{
69+
fontSize: this.state.fontSize,
70+
color: this.state.finished ? this.props.color : 'transparent',
71+
},
72+
]}
73+
>
74+
{this.props.children}
75+
</Text>
76+
);
77+
}
78+
}
79+
80+
export default AutoScaleText;

App/Navigation/NavigationBar.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ var Container = React.createClass({
4141
}
4242
});
4343

44+
const routeMapper = new NavigationBarRouteMapper();
45+
4446
var NavigationBar = {
4547
getInitialState: function() {
4648
return {};
@@ -120,7 +122,7 @@ var NavigationBar = {
120122

121123
return (
122124
<Navigator.NavigationBar
123-
routeMapper={new NavigationBarRouteMapper()}
125+
routeMapper={routeMapper}
124126
style={styles.navBar}
125127
/>
126128
);
@@ -131,7 +133,6 @@ var NavigationBar = {
131133
<View style={styles.appContainer}>
132134
<Navigator
133135
ref="navigator"
134-
debugOverlay={false}
135136
renderScene={this.renderScene}
136137
navBarHidden={this.props.navBarHidden}
137138
initialRouteStack={this.props.routeStack.path}

App/Navigation/NavigationTitle.js

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import React from 'react';
22
import {
33
View,
4-
StyleSheet
4+
StyleSheet,
5+
Dimensions,
6+
Platform,
57
} from 'react-native';
68

9+
const { width } = Dimensions.get('window');
10+
711
import cssVar from '../Lib/cssVar';
812

913
import DispatcherListener from '../Mixins/DispatcherListener';
1014
import AppConstants from '../Constants/AppConstants';
1115

12-
import Text from '../Components/Text';
16+
import AutoScaleText from '../Components/AutoScaleText';
1317

1418
var NavigationTitle = React.createClass({
1519
mixins: [DispatcherListener],
@@ -28,24 +32,54 @@ var NavigationTitle = React.createClass({
2832
}
2933
},
3034

35+
getButtonPadding() {
36+
const { route } = this.props;
37+
38+
// for some reason 70 is the magic number for Android
39+
if (Platform.OS === 'android') {
40+
return 70;
41+
}
42+
// if navRight is a text return 70
43+
if (route.navRight && route.navRight.label) {
44+
return 70;
45+
}
46+
// if navLeft is a text return 70
47+
if (route.navLeft && route.navLeft.label) {
48+
return 70;
49+
}
50+
51+
if (route.navBack && route.navBack.label) {
52+
return 70;
53+
}
54+
55+
return 40;
56+
},
57+
3158
render: function() {
3259
var title = this.state.updatedTitle || this.props.route.title;
3360
return (
34-
<Text style={styles.navBarTitleText}>
61+
<AutoScaleText
62+
style={[styles.navBarTitleText, {width: width - this.getButtonPadding() * 2}]}
63+
allowFontScaling={false}
64+
maxFontSize={20}
65+
maxHeight={50}
66+
color='white'
67+
>
3568
{title}
36-
</Text>
69+
</AutoScaleText>
3770
);
3871
}
3972
});
4073

74+
const marginVertical = Platform.OS === 'ios' ? 8 : 15;
4175
var styles = StyleSheet.create({
4276
navBarTitleText: {
43-
fontSize: 20,
4477
fontFamily: cssVar('fontRegular'),
45-
color: 'white',
4678
fontWeight: '500',
47-
marginVertical: 9,
48-
}
79+
marginVertical: marginVertical,
80+
textAlign: 'center',
81+
paddingBottom: 6,
82+
},
4983
});
5084

5185
export default NavigationTitle;

0 commit comments

Comments
 (0)