mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-10 09:12:46 +08:00
Dynamic Text Sizes for Text component
Summary: Dynamic Text Sizes for Text component. Text gains new prop - allowFontScaling (false by default). There is also AccessibilityManager module that allows you to tune multipliers per each content size category.
This commit is contained in:
@@ -87,7 +87,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{
|
||||
}
|
||||
|
||||
NSDictionary *fontDict = dict[@"font"];
|
||||
CTFontRef font = (__bridge CTFontRef)[self UIFont:nil withFamily:fontDict[@"fontFamily"] size:fontDict[@"fontSize"] weight:fontDict[@"fontWeight"] style:fontDict[@"fontStyle"]];
|
||||
CTFontRef font = (__bridge CTFontRef)[self UIFont:nil withFamily:fontDict[@"fontFamily"] size:fontDict[@"fontSize"] weight:fontDict[@"fontWeight"] style:fontDict[@"fontStyle"] scaleMultiplier:1.0];
|
||||
if (!font) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,32 @@
|
||||
|
||||
#import "RCTShadowRawText.h"
|
||||
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
@implementation RCTShadowRawText
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(contentSizeMultiplierDidChange:)
|
||||
name:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)contentSizeMultiplierDidChange:(NSNotification *)note
|
||||
{
|
||||
[self dirtyLayout];
|
||||
[self dirtyText];
|
||||
}
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
if (_text != text) {
|
||||
|
||||
@@ -30,6 +30,8 @@ extern NSString *const RCTReactTagAttributeName;
|
||||
@property (nonatomic, strong) UIColor *textDecorationColor;
|
||||
@property (nonatomic, assign) NSUnderlineStyle textDecorationStyle;
|
||||
@property (nonatomic, assign) RCTTextDecorationLineType textDecorationLine;
|
||||
@property (nonatomic, assign) CGFloat fontSizeMultiplier;
|
||||
@property (nonatomic, assign) BOOL allowFontScaling;
|
||||
|
||||
- (void)recomputeText;
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#import "RCTShadowText.h"
|
||||
|
||||
#import "RCTAccessibilityManager.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTShadowRawText.h"
|
||||
@@ -51,16 +54,31 @@ static css_dim_t RCTMeasure(void *context, float width)
|
||||
_letterSpacing = NAN;
|
||||
_isHighlighted = NO;
|
||||
_textDecorationStyle = NSUnderlineStyleSingle;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(contentSizeMultiplierDidChange:)
|
||||
name:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
NSString *superDescription = super.description;
|
||||
return [[superDescription substringToIndex:superDescription.length - 1] stringByAppendingFormat:@"; text: %@>", [self attributedString].string];
|
||||
}
|
||||
|
||||
- (void)contentSizeMultiplierDidChange:(NSNotification *)note
|
||||
{
|
||||
[self dirtyLayout];
|
||||
[self dirtyText];
|
||||
}
|
||||
|
||||
- (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks
|
||||
parentProperties:(NSDictionary *)parentProperties
|
||||
{
|
||||
@@ -190,7 +208,9 @@ static css_dim_t RCTMeasure(void *context, float width)
|
||||
[self _addAttribute:NSBackgroundColorAttributeName withValue:self.backgroundColor toAttributedString:attributedString];
|
||||
}
|
||||
|
||||
UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily size:fontSize weight:fontWeight style:fontStyle];
|
||||
UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily
|
||||
size:fontSize weight:fontWeight style:fontStyle
|
||||
scaleMultiplier:(_allowFontScaling && _fontSizeMultiplier > 0.0 ? _fontSizeMultiplier : 1.0)];
|
||||
[self _addAttribute:NSFontAttributeName withValue:font toAttributedString:attributedString];
|
||||
[self _addAttribute:NSKernAttributeName withValue:letterSpacing toAttributedString:attributedString];
|
||||
[self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString];
|
||||
@@ -232,8 +252,9 @@ static css_dim_t RCTMeasure(void *context, float width)
|
||||
[attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
|
||||
if (value) {
|
||||
NSParagraphStyle *paragraphStyle = (NSParagraphStyle *)value;
|
||||
if ([paragraphStyle maximumLineHeight] > _lineHeight) {
|
||||
self.lineHeight = [paragraphStyle maximumLineHeight];
|
||||
CGFloat maximumLineHeight = round([paragraphStyle maximumLineHeight] / self.fontSizeMultiplier);
|
||||
if (maximumLineHeight > self.lineHeight) {
|
||||
self.lineHeight = maximumLineHeight;
|
||||
}
|
||||
hasParagraphStyle = YES;
|
||||
}
|
||||
@@ -247,8 +268,9 @@ static css_dim_t RCTMeasure(void *context, float width)
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.alignment = _textAlign;
|
||||
paragraphStyle.baseWritingDirection = _writingDirection;
|
||||
paragraphStyle.minimumLineHeight = _lineHeight;
|
||||
paragraphStyle.maximumLineHeight = _lineHeight;
|
||||
CGFloat lineHeight = round(_lineHeight * self.fontSizeMultiplier);
|
||||
paragraphStyle.minimumLineHeight = lineHeight;
|
||||
paragraphStyle.maximumLineHeight = lineHeight;
|
||||
[attributedString addAttribute:NSParagraphStyleAttributeName
|
||||
value:paragraphStyle
|
||||
range:(NSRange){0, attributedString.length}];
|
||||
@@ -321,4 +343,26 @@ RCT_TEXT_PROPERTY(TextDecorationLine, _textDecorationLine, RCTTextDecorationLine
|
||||
RCT_TEXT_PROPERTY(TextDecorationStyle, _textDecorationStyle, NSUnderlineStyle);
|
||||
RCT_TEXT_PROPERTY(WritingDirection, _writingDirection, NSWritingDirection)
|
||||
|
||||
- (void)setAllowFontScaling:(BOOL)allowFontScaling
|
||||
{
|
||||
_allowFontScaling = allowFontScaling;
|
||||
for (RCTShadowView *child in [self reactSubviews]) {
|
||||
if ([child isKindOfClass:[RCTShadowText class]]) {
|
||||
[(RCTShadowText *)child setAllowFontScaling:allowFontScaling];
|
||||
}
|
||||
}
|
||||
[self dirtyText];
|
||||
}
|
||||
|
||||
- (void)setFontSizeMultiplier:(CGFloat)fontSizeMultiplier
|
||||
{
|
||||
_fontSizeMultiplier = fontSizeMultiplier;
|
||||
for (RCTShadowView *child in [self reactSubviews]) {
|
||||
if ([child isKindOfClass:[RCTShadowText class]]) {
|
||||
[(RCTShadowText *)child setFontSizeMultiplier:fontSizeMultiplier];
|
||||
}
|
||||
}
|
||||
[self dirtyText];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#import "RCTTextManager.h"
|
||||
|
||||
#import "RCTAccessibilityManager.h"
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
@@ -49,6 +50,7 @@ RCT_EXPORT_SHADOW_PROPERTY(textDecorationStyle, NSUnderlineStyle)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textDecorationColor, UIColor)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textDecorationLine, RCTTextDecorationLineType)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(writingDirection, NSWritingDirection)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(allowFontScaling, BOOL)
|
||||
|
||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry
|
||||
{
|
||||
@@ -69,6 +71,7 @@ RCT_EXPORT_SHADOW_PROPERTY(writingDirection, NSWritingDirection)
|
||||
RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text");
|
||||
|
||||
if ([shadowView isKindOfClass:[RCTShadowText class]]) {
|
||||
[(RCTShadowText *)shadowView setFontSizeMultiplier:self.bridge.accessibilityManager.multiplier];
|
||||
[(RCTShadowText *)shadowView recomputeText];
|
||||
} else if ([shadowView isKindOfClass:[RCTShadowRawText class]]) {
|
||||
RCTLogError(@"Raw text cannot be used outside of a <Text> tag. Not rendering string: '%@'",
|
||||
|
||||
@@ -30,6 +30,7 @@ var viewConfig = {
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, {
|
||||
isHighlighted: true,
|
||||
numberOfLines: true,
|
||||
allowFontScaling: true,
|
||||
}),
|
||||
uiViewClassName: 'RCTText',
|
||||
};
|
||||
@@ -99,15 +100,25 @@ var Text = React.createClass({
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: React.PropTypes.string,
|
||||
/**
|
||||
* Specifies should fonts scale to respect Text Size accessibility setting on iOS.
|
||||
*/
|
||||
allowFontScaling: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
viewConfig: viewConfig,
|
||||
|
||||
getInitialState: function() {
|
||||
getInitialState: function(): Object {
|
||||
return merge(this.touchableGetInitialState(), {
|
||||
isHighlighted: false,
|
||||
});
|
||||
},
|
||||
|
||||
getDefaultProps: function(): Object {
|
||||
return {
|
||||
allowFontScaling: true,
|
||||
};
|
||||
},
|
||||
|
||||
onStartShouldSetResponder: function(): bool {
|
||||
var shouldSetFromProps = this.props.onStartShouldSetResponder &&
|
||||
|
||||
Reference in New Issue
Block a user