Skip to content

Commit 4e87249

Browse files
Adam Comellafacebook-github-bot
Adam Comella
authored andcommitted
iOS: Add a maxFontSizeMultiplier prop to <Text> and <TextInput> (facebook#20915)
Summary: **Motivation** Whenever a user changes the system font size to its maximum allowable setting, React Native apps that allow font scaling can become unusable because the text gets too big. Experimenting with a native app like iMessage on iOS, the font size used for non-body text (e.g. header, navigational elements) is capped while the body text (e.g. text in the message bubbles) is allowed to grow. This PR introduces a new prop on `<Text>` and `<TextInput>` called `maxFontSizeMultiplier`. This enables devs to set the maximum allowed text scale factor on a Text/TextInput. The default is 0 which means no limit. Another PR will add this feature to Android. **Test Plan** I created a test app which utilizes all categories of values of `maxFontSizeMultiplier`: - `undefined`: inherit from parent - `0`: no limit - `1`, `1.2`: fixed limits I tried this with `Text`, `TextInput` with `value`, and `TextInput` with children. For `Text`, I also verified that nesting works properly (if a child `Text` doesn't specify `maxFontSizeMultiplier`, it inherits it from its parent). Lastly, we've been using a version of this in Skype for several months. **Release Notes** [GENERAL] [ENHANCEMENT] [Text/TextInput] - Added maxFontSizeMultiplier prop to prevent some text from getting unusably large as user increases OS's font scale setting (iOS) Adam Comella Microsoft Corp. Pull Request resolved: facebook#20915 Differential Revision: D9646739 Pulled By: shergin fbshipit-source-id: c823f59c1e342c22d6297b88b2cb11c5a1f10310
1 parent 632892c commit 4e87249

File tree

7 files changed

+39
-4
lines changed

7 files changed

+39
-4
lines changed

Libraries/Components/TextInput/TextInput.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ type Props = $ReadOnly<{|
177177
autoCorrect?: ?boolean,
178178
autoFocus?: ?boolean,
179179
allowFontScaling?: ?boolean,
180+
maxFontSizeMultiplier?: ?boolean,
180181
editable?: ?boolean,
181182
keyboardType?: ?KeyboardType,
182183
returnKeyType?: ?ReturnKeyType,
@@ -367,6 +368,14 @@ const TextInput = createReactClass({
367368
* default is `true`.
368369
*/
369370
allowFontScaling: PropTypes.bool,
371+
/**
372+
* Specifies largest possible scale a font can reach when `allowFontScaling` is enabled.
373+
* Possible values:
374+
* `null/undefined` (default): inherit from the parent node or the global default (0)
375+
* `0`: no max, ignore parent/global default
376+
* `>= 1`: sets the maxFontSizeMultiplier of this node to this value
377+
*/
378+
maxFontSizeMultiplier: PropTypes.number,
370379
/**
371380
* If `false`, text is not editable. The default value is `true`.
372381
*/
@@ -933,7 +942,11 @@ const TextInput = createReactClass({
933942
);
934943
if (childCount >= 1) {
935944
children = (
936-
<Text style={props.style} allowFontScaling={props.allowFontScaling}>
945+
<Text
946+
style={props.style}
947+
allowFontScaling={props.allowFontScaling}
948+
maxFontSizeMultiplier={props.maxFontSizeMultiplier}
949+
>
937950
{children}
938951
</Text>
939952
);

Libraries/Text/BaseText/RCTBaseTextViewManager.m

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ - (RCTShadowView *)shadowView
3636
RCT_REMAP_SHADOW_PROPERTY(fontStyle, textAttributes.fontStyle, NSString)
3737
RCT_REMAP_SHADOW_PROPERTY(fontVariant, textAttributes.fontVariant, NSArray)
3838
RCT_REMAP_SHADOW_PROPERTY(allowFontScaling, textAttributes.allowFontScaling, BOOL)
39+
RCT_REMAP_SHADOW_PROPERTY(maxFontSizeMultiplier, textAttributes.maxFontSizeMultiplier, CGFloat)
3940
RCT_REMAP_SHADOW_PROPERTY(letterSpacing, textAttributes.letterSpacing, CGFloat)
4041
// Paragraph Styles
4142
RCT_REMAP_SHADOW_PROPERTY(lineHeight, textAttributes.lineHeight, CGFloat)

Libraries/Text/RCTTextAttributes.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern NSString *const RCTTextAttributesTagAttributeName;
3131
@property (nonatomic, copy, nullable) NSString *fontFamily;
3232
@property (nonatomic, assign) CGFloat fontSize;
3333
@property (nonatomic, assign) CGFloat fontSizeMultiplier;
34+
@property (nonatomic, assign) CGFloat maxFontSizeMultiplier;
3435
@property (nonatomic, copy, nullable) NSString *fontWeight;
3536
@property (nonatomic, copy, nullable) NSString *fontStyle;
3637
@property (nonatomic, copy, nullable) NSArray<NSString *> *fontVariant;
@@ -71,7 +72,7 @@ extern NSString *const RCTTextAttributesTagAttributeName;
7172
- (UIFont *)effectiveFont;
7273

7374
/**
74-
* Font size multiplier reflects `allowFontScaling` and `fontSizeMultiplier`.
75+
* Font size multiplier reflects `allowFontScaling`, `fontSizeMultiplier`, and `maxFontSizeMultiplier`.
7576
*/
7677
- (CGFloat)effectiveFontSizeMultiplier;
7778

Libraries/Text/RCTTextAttributes.m

+12-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ - (instancetype)init
2424
_lineHeight = NAN;
2525
_textDecorationStyle = NSUnderlineStyleSingle;
2626
_fontSizeMultiplier = NAN;
27+
_maxFontSizeMultiplier = NAN;
2728
_alignment = NSTextAlignmentNatural;
2829
_baseWritingDirection = NSWritingDirectionNatural;
2930
_textShadowRadius = NAN;
@@ -49,6 +50,7 @@ - (void)applyTextAttributes:(RCTTextAttributes *)textAttributes
4950
_fontFamily = textAttributes->_fontFamily ?: _fontFamily;
5051
_fontSize = !isnan(textAttributes->_fontSize) ? textAttributes->_fontSize : _fontSize;
5152
_fontSizeMultiplier = !isnan(textAttributes->_fontSizeMultiplier) ? textAttributes->_fontSizeMultiplier : _fontSizeMultiplier;
53+
_maxFontSizeMultiplier = !isnan(textAttributes->_maxFontSizeMultiplier) ? textAttributes->_maxFontSizeMultiplier : _maxFontSizeMultiplier;
5254
_fontWeight = textAttributes->_fontWeight ?: _fontWeight;
5355
_fontStyle = textAttributes->_fontStyle ?: _fontStyle;
5456
_fontVariant = textAttributes->_fontVariant ?: _fontVariant;
@@ -191,7 +193,15 @@ - (UIFont *)effectiveFont
191193

192194
- (CGFloat)effectiveFontSizeMultiplier
193195
{
194-
return !RCTHasFontHandlerSet() && _allowFontScaling && !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0;
196+
bool fontScalingEnabled = !RCTHasFontHandlerSet() && _allowFontScaling;
197+
198+
if (fontScalingEnabled) {
199+
CGFloat fontSizeMultiplier = !isnan(_fontSizeMultiplier) ? _fontSizeMultiplier : 1.0;
200+
CGFloat maxFontSizeMultiplier = !isnan(_maxFontSizeMultiplier) ? _maxFontSizeMultiplier : 0.0;
201+
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
202+
} else {
203+
return 1.0;
204+
}
195205
}
196206

197207
- (UIColor *)effectiveForegroundColor
@@ -260,6 +270,7 @@ - (BOOL)isEqual:(RCTTextAttributes *)textAttributes
260270
RCTTextAttributesCompareObjects(_fontFamily) &&
261271
RCTTextAttributesCompareFloats(_fontSize) &&
262272
RCTTextAttributesCompareFloats(_fontSizeMultiplier) &&
273+
RCTTextAttributesCompareFloats(_maxFontSizeMultiplier) &&
263274
RCTTextAttributesCompareStrings(_fontWeight) &&
264275
RCTTextAttributesCompareObjects(_fontStyle) &&
265276
RCTTextAttributesCompareObjects(_fontVariant) &&

Libraries/Text/Text.js

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const viewConfig = {
5858
numberOfLines: true,
5959
ellipsizeMode: true,
6060
allowFontScaling: true,
61+
maxFontSizeMultiplier: true,
6162
disabled: true,
6263
selectable: true,
6364
selectionColor: true,
@@ -263,6 +264,7 @@ const RCTVirtualText =
263264
validAttributes: {
264265
...ReactNativeViewAttributes.UIView,
265266
isHighlighted: true,
267+
maxFontSizeMultiplier: true,
266268
},
267269
uiViewClassName: 'RCTVirtualText',
268270
}));

Libraries/Text/Text/RCTTextViewManager.m

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ @interface RCTTextViewManager () <RCTUIManagerObserver>
2424
@implementation RCTTextViewManager
2525
{
2626
NSHashTable<RCTTextShadowView *> *_shadowViews;
27-
CGFloat _fontSizeMultiplier;
2827
}
2928

3029
RCT_EXPORT_MODULE(RCTText)

Libraries/Text/TextPropTypes.js

+8
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ module.exports = {
100100
* See https://facebook.github.io/react-native/docs/text.html#allowfontscaling
101101
*/
102102
allowFontScaling: PropTypes.bool,
103+
/**
104+
* Specifies largest possible scale a font can reach when `allowFontScaling` is enabled.
105+
* Possible values:
106+
* `null/undefined` (default): inherit from the parent node or the global default (0)
107+
* `0`: no max, ignore parent/global default
108+
* `>= 1`: sets the maxFontSizeMultiplier of this node to this value
109+
*/
110+
maxFontSizeMultiplier: PropTypes.number,
103111
/**
104112
* Indicates whether the view is an accessibility element.
105113
*

0 commit comments

Comments
 (0)