Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS: Support allowFontScaling on TextInput #14030

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ const TextInput = createReactClass({
* @platform android
*/
autoGrow: PropTypes.bool,
/**
* Specifies whether fonts should scale to respect Text Size accessibility settings. The
* default is `true`.
*/
allowFontScaling: PropTypes.bool,
/**
* If `false`, text is not editable. The default value is `true`.
*/
Expand Down Expand Up @@ -550,7 +555,11 @@ const TextInput = createReactClass({
*/
caretHidden: PropTypes.bool,
},

getDefaultProps(): Object {
return {
allowFontScaling: true,
};
},
/**
* `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We
* make `this` look like an actual native component class.
Expand Down Expand Up @@ -688,7 +697,7 @@ const TextInput = createReactClass({
'Cannot specify both value and children.'
);
if (childCount >= 1) {
children = <Text style={props.style}>{children}</Text>;
children = <Text style={props.style} allowFontScaling={props.allowFontScaling}>{children}</Text>;
}
if (props.inputView) {
children = [children, props.inputView];
Expand Down
14 changes: 14 additions & 0 deletions Libraries/Text/RCTTextField.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTFont.h>
#import <React/RCTUIManager.h>
#import <React/RCTUtils.h>
#import <React/UIView+React.h>
Expand Down Expand Up @@ -55,6 +56,19 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
return _backedTextInput;
}

- (void)updateFont
{
CGFloat scaleMultiplier = self.allowFontScaling ? self.fontSizeMultiplier : 1.0;

_backedTextInput.font = [RCTFont updateFont:nil
withFamily:self.fontFamily
size:self.fontSize
weight:self.fontWeight
style:self.fontStyle
variant:nil
scaleMultiplier:scaleMultiplier];
}

- (void)sendKeyValueForString:(NSString *)string
{
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeKeyPress
Expand Down
13 changes: 9 additions & 4 deletions Libraries/Text/RCTTextFieldManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ - (UIView *)view
RCT_REMAP_VIEW_PROPERTY(selectionColor, backedTextInputView.tintColor, UIColor)
RCT_REMAP_VIEW_PROPERTY(spellCheck, backedTextInputView.spellCheckingType, UITextSpellCheckingType)
RCT_REMAP_VIEW_PROPERTY(textAlign, backedTextInputView.textAlignment, NSTextAlignment)
RCT_EXPORT_VIEW_PROPERTY(allowFontScaling, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(maxLength, NSNumber)
Expand All @@ -63,19 +64,23 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(onSelectionChange, RCTDirectEventBlock)
RCT_CUSTOM_VIEW_PROPERTY(fontSize, NSNumber, RCTTextField)
{
view.backedTextInputView.font = [RCTFont updateFont:view.backedTextInputView.font withSize:json ?: @(defaultView.backedTextInputView.font.pointSize)];
view.fontSize = json ?: @(defaultView.backedTextInputView.font.pointSize);
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused RCTTextField)
{
view.backedTextInputView.font = [RCTFont updateFont:view.backedTextInputView.font withWeight:json]; // defaults to normal
view.fontWeight = json; // defaults to normal
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused RCTTextField)
{
view.backedTextInputView.font = [RCTFont updateFont:view.backedTextInputView.font withStyle:json]; // defaults to normal
view.fontStyle = json; // defaults to normal
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, RCTTextField)
{
view.backedTextInputView.font = [RCTFont updateFont:view.backedTextInputView.font withFamily:json ?: defaultView.backedTextInputView.font.familyName];
view.fontFamily = json ?: defaultView.backedTextInputView.font.familyName;
[view updateFont];
}
RCT_EXPORT_VIEW_PROPERTY(mostRecentEventCount, NSInteger)

Expand Down
11 changes: 11 additions & 0 deletions Libraries/Text/RCTTextInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@

#import "RCTBackedTextInputViewProtocol.h"

@class RCTAccessibilityManager;
@class RCTBridge;
@class RCTEventDispatcher;
@class RCTTextSelection;

@interface RCTTextInput : RCTView {
@protected
RCTAccessibilityManager *_accessibilityManager;
RCTBridge *_bridge;
RCTEventDispatcher *_eventDispatcher;
NSInteger _nativeEventCount;
Expand Down Expand Up @@ -47,8 +49,17 @@
@property (nonatomic, assign) BOOL clearTextOnFocus;
@property (nonatomic, copy) RCTTextSelection *selection;

@property (nonatomic, assign) BOOL allowFontScaling;
@property (nonatomic, copy) NSString *fontFamily;
@property (nonatomic, strong) NSNumber *fontSize;
@property (nonatomic, assign) CGFloat fontSizeMultiplier;
@property (nonatomic, copy) NSString *fontStyle;
@property (nonatomic, copy) NSString *fontWeight;

- (void)invalidateContentSize;

- (void)updateFont;

// Temporary exposure of particial `RCTBackedTextInputDelegate` support.
// In the future all methods of the protocol should move to this class.
- (BOOL)textInputShouldBeginEditing;
Expand Down
43 changes: 43 additions & 0 deletions Libraries/Text/RCTTextInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#import "RCTTextInput.h"

#import <React/RCTAccessibilityManager.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
Expand All @@ -28,7 +29,15 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge

if (self = [super initWithFrame:CGRectZero]) {
_bridge = bridge;
_accessibilityManager = bridge.accessibilityManager;
_eventDispatcher = bridge.eventDispatcher;
_fontSizeMultiplier = _accessibilityManager.multiplier;
[self updateFont];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contentSizeMultiplierDidChange)
name:RCTAccessibilityManagerDidUpdateMultiplierNotification
object:_accessibilityManager];
}

return self;
Expand All @@ -38,14 +47,48 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder)
RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id<RCTBackedTextInputViewProtocol>)backedTextInputView
{
RCTAssert(NO, @"-[RCTTextInput backedTextInputView] must be implemented in subclass.");
return nil;
}

- (void)updateFont
{
RCTAssert(NO, @"-[RCTTextInput updateFont] must be implemented in subclass.");
}

- (void)contentSizeMultiplierDidChange
{
self.fontSizeMultiplier = _accessibilityManager.multiplier;
}

#pragma mark - Properties

- (void)setAllowFontScaling:(BOOL)allowFontScaling
{
_allowFontScaling = allowFontScaling;
[self updateFont];

}

- (void)setFontSizeMultiplier:(CGFloat)fontSizeMultiplier
{
_fontSizeMultiplier = fontSizeMultiplier;

if (_fontSizeMultiplier == 0) {
RCTLogError(@"fontSizeMultiplier value must be > zero.");
_fontSizeMultiplier = 1.0;
}

[self updateFont];
}

- (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets
{
_reactPaddingInsets = reactPaddingInsets;
Expand Down
21 changes: 21 additions & 0 deletions Libraries/Text/RCTTextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTFont.h>
#import <React/RCTUIManager.h>
#import <React/RCTUtils.h>
#import <React/UIView+React.h>
Expand Down Expand Up @@ -70,6 +71,26 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
return _backedTextInput;
}

- (void)updateFont
{
CGFloat scaleMultiplier = self.allowFontScaling ? self.fontSizeMultiplier : 1.0;

self.font = [RCTFont updateFont:nil
withFamily:self.fontFamily
size:self.fontSize
weight:self.fontWeight
style:self.fontStyle
variant:nil
scaleMultiplier:scaleMultiplier];

// Because the font changed, the TextInput may take up more space now so we call
// invalidateContentSize. However, if there's currently no text to render, then
// there's no need to call invalidateContentSize.
if ([self text].length != 0) {
[self invalidateContentSize];
}
}

#pragma mark - RCTComponent

- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)index
Expand Down
13 changes: 9 additions & 4 deletions Libraries/Text/RCTTextViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ - (UIView *)view
RCT_REMAP_VIEW_PROPERTY(selectionColor, backedTextInputView.tintColor, UIColor)
RCT_REMAP_VIEW_PROPERTY(spellCheck, backedTextInputView.spellCheckingType, UITextSpellCheckingType)
RCT_REMAP_VIEW_PROPERTY(textAlign, backedTextInputView.textAlignment, NSTextAlignment)
RCT_EXPORT_VIEW_PROPERTY(allowFontScaling, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(maxLength, NSNumber)
Expand All @@ -66,19 +67,23 @@ - (UIView *)view

RCT_CUSTOM_VIEW_PROPERTY(fontSize, NSNumber, RCTTextView)
{
view.font = [RCTFont updateFont:view.font withSize:json ?: @(defaultView.font.pointSize)];
view.fontSize = json ?: @(defaultView.font.pointSize);
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused RCTTextView)
{
view.font = [RCTFont updateFont:view.font withWeight:json]; // defaults to normal
view.fontWeight = json; //defaults to normal
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused RCTTextView)
{
view.font = [RCTFont updateFont:view.font withStyle:json]; // defaults to normal
view.fontStyle = json; //defaults to normal
[view updateFont];
}
RCT_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, RCTTextView)
{
view.font = [RCTFont updateFont:view.font withFamily:json ?: defaultView.font.familyName];
view.fontFamily = json ?: defaultView.font.familyName;
[view updateFont];
}
RCT_EXPORT_VIEW_PROPERTY(mostRecentEventCount, NSInteger)

Expand Down