diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testTextExample_1@2x.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testTextExample_1@2x.png index 41970dbac17737..cec7ad5bc743fb 100644 Binary files a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testTextExample_1@2x.png and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-js-UIExplorerApp.ios/testTextExample_1@2x.png differ diff --git a/Examples/UIExplorer/js/TextExample.ios.js b/Examples/UIExplorer/js/TextExample.ios.js index 3262aeed004a2a..a424fc1b4460f3 100644 --- a/Examples/UIExplorer/js/TextExample.ios.js +++ b/Examples/UIExplorer/js/TextExample.ios.js @@ -341,6 +341,18 @@ exports.examples = [ </Text> ); }, +}, { + title: 'IOS Line Height', + render: function() { + return ( + <Text> + <Text style={{IOSLineHeight: 35}}> + A lot of space between the lines of this long passage that should + wrap twice. This text is vertically centered. + </Text> + </Text> + ); + }, }, { title: 'Empty Text', description: 'It\'s ok to have Text with zero or null children.', diff --git a/Libraries/Text/RCTShadowText.h b/Libraries/Text/RCTShadowText.h index ed0cc5d6a1a5b5..bae4a112290104 100644 --- a/Libraries/Text/RCTShadowText.h +++ b/Libraries/Text/RCTShadowText.h @@ -23,6 +23,7 @@ extern NSString *const RCTReactTagAttributeName; @property (nonatomic, assign) BOOL isHighlighted; @property (nonatomic, assign) CGFloat letterSpacing; @property (nonatomic, assign) CGFloat lineHeight; +@property (nonatomic, assign) CGFloat IOSLineHeight; @property (nonatomic, assign) NSUInteger numberOfLines; @property (nonatomic, assign) NSLineBreakMode lineBreakMode; @property (nonatomic, assign) CGSize shadowOffset; diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 32e73997facaa7..39ae79ad59b45f 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -347,11 +347,11 @@ - (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attrib { // check if we have lineHeight set on self __block BOOL hasParagraphStyle = NO; - if (_lineHeight || _textAlign) { + if (_IOSLineHeight || _lineHeight || _textAlign) { hasParagraphStyle = YES; } - __block float newLineHeight = _lineHeight ?: 0.0; + __block float newLineHeight = _IOSLineHeight ?: _lineHeight ?: 0.0; CGFloat fontSizeMultiplier = _allowFontScaling ? _fontSizeMultiplier : 1.0; @@ -403,12 +403,22 @@ - (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attrib NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; paragraphStyle.alignment = _textAlign; paragraphStyle.baseWritingDirection = _writingDirection; - CGFloat lineHeight = round(_lineHeight * fontSizeMultiplier); + CGFloat lineHeight = round(newLineHeight * fontSizeMultiplier); if (heightOfTallestSubview > lineHeight) { lineHeight = ceilf(heightOfTallestSubview); } paragraphStyle.minimumLineHeight = lineHeight; paragraphStyle.maximumLineHeight = lineHeight; + + if (_IOSLineHeight) { + // vertically center text + CGFloat fontSize = _fontSize && !isnan(_fontSize) ? _fontSize : UIFont.systemFontSize; + fontSize *= fontSizeMultiplier; + + [attributedString addAttribute:NSBaselineOffsetAttributeName + value:@(lineHeight/2 - fontSize/2) + range:(NSRange){0, attributedString.length}]; + } [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:(NSRange){0, attributedString.length}]; @@ -482,6 +492,7 @@ - (void)set##setProp:(type)value; \ RCT_TEXT_PROPERTY(IsHighlighted, _isHighlighted, BOOL) RCT_TEXT_PROPERTY(LetterSpacing, _letterSpacing, CGFloat) RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat) +RCT_TEXT_PROPERTY(IOSLineHeight, _IOSLineHeight, CGFloat) RCT_TEXT_PROPERTY(NumberOfLines, _numberOfLines, NSUInteger) RCT_TEXT_PROPERTY(LineBreakMode, _lineBreakMode, NSLineBreakMode) RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment) diff --git a/Libraries/Text/RCTTextManager.m b/Libraries/Text/RCTTextManager.m index 676ff9bb2063b8..34eb4f5a67bd87 100644 --- a/Libraries/Text/RCTTextManager.m +++ b/Libraries/Text/RCTTextManager.m @@ -63,6 +63,7 @@ - (RCTShadowView *)shadowView RCT_EXPORT_SHADOW_PROPERTY(isHighlighted, BOOL) RCT_EXPORT_SHADOW_PROPERTY(letterSpacing, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(lineHeight, CGFloat) +RCT_EXPORT_SHADOW_PROPERTY(IOSLineHeight, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(numberOfLines, NSUInteger) RCT_EXPORT_SHADOW_PROPERTY(lineBreakMode, NSLineBreakMode) RCT_EXPORT_SHADOW_PROPERTY(textAlign, NSTextAlignment) diff --git a/Libraries/Text/TextStylePropTypes.js b/Libraries/Text/TextStylePropTypes.js index daa3094a6361c8..381d1eae2b2043 100644 --- a/Libraries/Text/TextStylePropTypes.js +++ b/Libraries/Text/TextStylePropTypes.js @@ -40,6 +40,12 @@ var TextStylePropTypes = Object.assign(Object.create(ViewStylePropTypes), { */ letterSpacing: ReactPropTypes.number, lineHeight: ReactPropTypes.number, + /** + * @platform ios + * + * Vertically centers the text within a line on iOS. + */ + IOSLineHeight: ReactPropTypes.number, /** * Specifies text alignment. The value 'justify' is only supported on iOS and * fallbacks to `left` on Android.