Skip to content

Commit d7d157b

Browse files
elliscwcalphatrl
authored andcommitted
feat: Gapless underline text
1 parent e395e98 commit d7d157b

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

Libraries/Text/RCTTextAttributes.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@ - (NSParagraphStyle *)effectiveParagraphStyle
165165
attributes[NSUnderlineColorAttributeName] = _textDecorationColor ?: effectiveForegroundColor;
166166
}
167167

168-
// @Taskadev1 Turn background color into underline highlight
168+
// @Taskadev1 Turn background highlight into underline highlight
169169
if (_backgroundColor || !isnan(_opacity)) {
170170
isTextDecorationEnabled = YES;
171171
attributes[NSUnderlineColorAttributeName] = self.effectiveBackgroundColor;
172-
attributes[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleThick + NSUnderlineStyleThick);
172+
attributes[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleThick + NSUnderlineStyleSingle);
173173
}
174174

175175
// Shadow

Libraries/Text/Text/RCTTextShadowView.m

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,50 @@
1515
#import "NSTextStorage+FontScaling.h"
1616
#import <React/RCTTextView.h>
1717

18+
// @Taskadev1 A custom layout manager to support gapless underlined text
19+
@interface CustomLayoutManager : NSLayoutManager {
20+
}
21+
- (void)drawUnderlineForRect:(CGRect)rect;
22+
- (void)drawUnderlineForGlyphRange:(NSRange)glyphRange
23+
underlineType:(NSUnderlineStyle)underlineVal
24+
baselineOffset:(CGFloat)baselineOffset
25+
lineFragmentRect:(CGRect)lineRect
26+
lineFragmentGlyphRange:(NSRange)lineGlyphRange
27+
containerOrigin:(CGPoint)containerOrigin;
28+
@end
29+
30+
@implementation CustomLayoutManager
31+
32+
- (void)drawUnderlineForRect:(CGRect)rect
33+
{
34+
UIBezierPath *path = [UIBezierPath new];
35+
path.lineWidth = 3.5;
36+
[path moveToPoint: CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect))];
37+
[path addLineToPoint: CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect))];
38+
[path stroke];
39+
}
40+
41+
- (void)drawUnderlineForGlyphRange:(NSRange)glyphRange
42+
underlineType:(NSUnderlineStyle)underlineVal
43+
baselineOffset:(CGFloat)baselineOffset
44+
lineFragmentRect:(CGRect)lineRect
45+
lineFragmentGlyphRange:(NSRange)lineGlyphRange
46+
containerOrigin:(CGPoint)containerOrigin
47+
{
48+
NSTextContainer *textContainer = [self textContainerForGlyphAtIndex:glyphRange.location effectiveRange: nil];
49+
CGRect boundingRect = [self boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
50+
CGRect offsetRect = CGRectOffset(boundingRect, containerOrigin.x, containerOrigin.y );
51+
UIColor *color = [self.textStorage attribute:NSUnderlineColorAttributeName atIndex:glyphRange.location effectiveRange: nil];
52+
53+
if (color) {
54+
[color setStroke];
55+
}
56+
57+
[self drawUnderlineForRect:offsetRect];
58+
}
59+
60+
@end
61+
1862
@implementation RCTTextShadowView
1963
{
2064
__weak RCTBridge *_bridge;
@@ -232,7 +276,7 @@ - (NSTextStorage *)textStorageAndLayoutManagerThatFitsSize:(CGSize)size
232276
_maximumNumberOfLines > 0 ? _lineBreakMode : NSLineBreakByClipping;
233277
textContainer.maximumNumberOfLines = _maximumNumberOfLines;
234278

235-
NSLayoutManager *layoutManager = [NSLayoutManager new];
279+
CustomLayoutManager *layoutManager = [CustomLayoutManager new];
236280
layoutManager.usesFontLeading = NO;
237281
[layoutManager addTextContainer:textContainer];
238282

0 commit comments

Comments
 (0)