Add letterSpacing style property for Text

Summary:
Fixes #457
Closes https://github.com/facebook/react-native/pull/482
Github Author: Vladimir Kurchatkin <vladimir.kurchatkin@gmail.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
Vladimir Kurchatkin 2015-05-12 00:25:08 -07:00 committed by Christopher Chedeau
parent 02d875869a
commit a142ed50ff
8 changed files with 57 additions and 36 deletions

View File

@ -218,6 +218,26 @@ exports.examples = [
</View>
);
},
}, {
title: 'Letter Spacing',
render: function() {
return (
<View>
<Text style={{letterSpacing: 0}}>
letterSpacing = 0
</Text>
<Text style={{letterSpacing: 2, marginTop: 5}}>
letterSpacing = 2
</Text>
<Text style={{letterSpacing: 9, marginTop: 5}}>
letterSpacing = 9
</Text>
<Text style={{letterSpacing: -1, marginTop: 5}}>
letterSpacing = -1
</Text>
</View>
);
},
}, {
title: 'Spaces',
render: function() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 273 KiB

View File

@ -88,35 +88,19 @@
XCTAssertTrue(foundElement, @"Cound't find element with '<View>' text in %d seconds", TIMEOUT_SECONDS);
}
- (void)testViewExampleSnapshot
{
[_runner runTest:_cmd module:@"ViewExample"];
#define RCT_SNAPSHOT_TEST(name, reRecord) \
- (void)test##name##Snapshot \
{ \
_runner.recordMode |= reRecord; \
[_runner runTest:_cmd module:@#name]; \
}
- (void)testLayoutExampleSnapshot
{
[_runner runTest:_cmd module:@"LayoutExample"];
}
- (void)testTextExampleSnapshot
{
[_runner runTest:_cmd module:@"TextExample"];
}
- (void)testSwitchExampleSnapshot
{
[_runner runTest:_cmd module:@"SwitchExample"];
}
- (void)testSliderExampleSnapshot
{
[_runner runTest:_cmd module:@"SliderExample"];
}
- (void)testTabBarExampleSnapshot
{
[_runner runTest:_cmd module:@"TabBarExample"];
}
RCT_SNAPSHOT_TEST(ViewExample, NO)
RCT_SNAPSHOT_TEST(LayoutExample, NO)
RCT_SNAPSHOT_TEST(TextExample, NO)
RCT_SNAPSHOT_TEST(SwitchExample, NO)
RCT_SNAPSHOT_TEST(SliderExample, NO)
RCT_SNAPSHOT_TEST(TabBarExample, NO)
// Make sure this test runs last
- (void)testZZZ_NotInRecordMode

View File

@ -22,6 +22,7 @@ extern NSString *const RCTReactTagAttributeName;
@property (nonatomic, copy) NSString *fontWeight;
@property (nonatomic, copy) NSString *fontStyle;
@property (nonatomic, assign) BOOL isHighlighted;
@property (nonatomic, assign) CGFloat letterSpacing;
@property (nonatomic, assign) CGFloat lineHeight;
@property (nonatomic, assign) NSUInteger maximumNumberOfLines;
@property (nonatomic, assign) CGSize shadowOffset;
@ -30,6 +31,7 @@ extern NSString *const RCTReactTagAttributeName;
// Not exposed to JS
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, assign) NSLineBreakMode truncationMode;
@property (nonatomic, assign) CGFloat effectiveLetterSpacing;
@property (nonatomic, copy, readonly) NSAttributedString *attributedString;
@property (nonatomic, strong, readonly) NSLayoutManager *layoutManager;

View File

@ -40,11 +40,15 @@ static css_dim_t RCTMeasure(void *context, float width)
css_dim_t result;
result.dimensions[CSS_WIDTH] = RCTCeilPixelValue(computedSize.width);
if (shadowText.effectiveLetterSpacing < 0) {
result.dimensions[CSS_WIDTH] -= shadowText.effectiveLetterSpacing;
}
result.dimensions[CSS_HEIGHT] = RCTCeilPixelValue(computedSize.height);
return result;
}
@implementation RCTShadowText {
@implementation RCTShadowText
{
NSLayoutManager *_layoutManager;
NSTextContainer *_textContainer;
NSAttributedString *_cachedAttributedString;
@ -55,6 +59,7 @@ static css_dim_t RCTMeasure(void *context, float width)
{
if ((self = [super init])) {
_fontSize = NAN;
_letterSpacing = NAN;
_isHighlighted = NO;
_textContainer = [[NSTextContainer alloc] init];
@ -71,22 +76,24 @@ static css_dim_t RCTMeasure(void *context, float width)
- (NSAttributedString *)attributedString
{
return [self _attributedStringWithFontFamily:nil
fontSize:0
fontSize:nil
fontWeight:nil
fontStyle:nil];
fontStyle:nil
letterSpacing:nil];
}
- (NSAttributedString *)_attributedStringWithFontFamily:(NSString *)fontFamily
fontSize:(CGFloat)fontSize
fontSize:(NSNumber *)fontSize
fontWeight:(NSString *)fontWeight
fontStyle:(NSString *)fontStyle
letterSpacing:(NSNumber *)letterSpacing
{
if (![self isTextDirty] && _cachedAttributedString) {
return _cachedAttributedString;
}
if (_fontSize && !isnan(_fontSize)) {
fontSize = _fontSize;
fontSize = @(_fontSize);
}
if (_fontWeight) {
fontWeight = _fontWeight;
@ -97,12 +104,17 @@ static css_dim_t RCTMeasure(void *context, float width)
if (_fontFamily) {
fontFamily = _fontFamily;
}
if (!isnan(_letterSpacing)) {
letterSpacing = @(_letterSpacing);
}
_effectiveLetterSpacing = letterSpacing.doubleValue;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
for (RCTShadowView *child in [self reactSubviews]) {
if ([child isKindOfClass:[RCTShadowText class]]) {
RCTShadowText *shadowText = (RCTShadowText *)child;
[attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight fontStyle:fontStyle]];
[attributedString appendAttributedString:[shadowText _attributedStringWithFontFamily:fontFamily fontSize:fontSize fontWeight:fontWeight fontStyle:fontStyle letterSpacing:letterSpacing]];
} else if ([child isKindOfClass:[RCTShadowRawText class]]) {
RCTShadowRawText *shadowRawText = (RCTShadowRawText *)child;
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[shadowRawText text] ?: @""]];
@ -123,8 +135,9 @@ static css_dim_t RCTMeasure(void *context, float width)
[self _addAttribute:NSBackgroundColorAttributeName withValue:self.textBackgroundColor toAttributedString:attributedString];
}
_font = [RCTConvert UIFont:nil withFamily:fontFamily size:@(fontSize) weight:fontWeight style:fontStyle];
_font = [RCTConvert UIFont:nil withFamily:fontFamily size:fontSize weight:fontWeight style:fontStyle];
[self _addAttribute:NSFontAttributeName withValue:_font toAttributedString:attributedString];
[self _addAttribute:NSKernAttributeName withValue:letterSpacing toAttributedString:attributedString];
[self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString];
[self _setParagraphStyleOnAttributedString:attributedString];
@ -143,7 +156,7 @@ static css_dim_t RCTMeasure(void *context, float width)
- (void)_addAttribute:(NSString *)attribute withValue:(id)attributeValue toAttributedString:(NSMutableAttributedString *)attributedString
{
[attributedString enumerateAttribute:attribute inRange:NSMakeRange(0, [attributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
if (!value) {
if (!value && attributeValue) {
[attributedString addAttribute:attribute value:attributeValue range:range];
}
}];
@ -223,6 +236,7 @@ RCT_TEXT_PROPERTY(Color, _color, UIColor *);
RCT_TEXT_PROPERTY(FontFamily, _fontFamily, NSString *);
RCT_TEXT_PROPERTY(FontSize, _fontSize, CGFloat);
RCT_TEXT_PROPERTY(FontWeight, _fontWeight, NSString *);
RCT_TEXT_PROPERTY(LetterSpacing, _letterSpacing, CGFloat);
RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat);
RCT_TEXT_PROPERTY(ShadowOffset, _shadowOffset, CGSize);
RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment);

View File

@ -14,7 +14,6 @@
@property (nonatomic, strong) NSLayoutManager *layoutManager;
@property (nonatomic, strong) NSTextContainer *textContainer;
@property (nonatomic, copy) NSAttributedString *attributedText;
@property (nonatomic, assign) UIEdgeInsets contentInset;
@end

View File

@ -45,6 +45,7 @@ RCT_EXPORT_SHADOW_PROPERTY(fontSize, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(fontWeight, NSString)
RCT_EXPORT_SHADOW_PROPERTY(fontStyle, NSString)
RCT_EXPORT_SHADOW_PROPERTY(isHighlighted, BOOL)
RCT_EXPORT_SHADOW_PROPERTY(letterSpacing, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(lineHeight, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger)
RCT_EXPORT_SHADOW_PROPERTY(shadowOffset, CGSize)

View File

@ -32,6 +32,7 @@ var TextStylePropTypes = Object.assign(Object.create(ViewStylePropTypes), {
writingDirection: ReactPropTypes.oneOf(
['auto' /*default*/, 'ltr', 'rtl']
),
letterSpacing: ReactPropTypes.number,
});
// Text doesn't support padding correctly (#4841912)