Skip to content

Commit 346309e

Browse files
Mehdi Mulanikelset
authored andcommitted
Text: send metrics after rendering (iOS)
Summary: This adds a callback for <Text> to get metrics about the rendered text. It's divided by line but that could be changed to "fragments" (which makes more sense for multi-lingual). Right now by line is convenient as you frequently want to know where the first and last line end (though we could make this work with fragments I suppose). Reviewed By: shergin Differential Revision: D9440914 fbshipit-source-id: bb011bb7a52438380d3f604ffe7019b98c18d978
1 parent fd781c3 commit 346309e

File tree

6 files changed

+372
-1
lines changed

6 files changed

+372
-1
lines changed

Libraries/Text/Text.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ const viewConfig = {
6464
adjustsFontSizeToFit: true,
6565
minimumFontScale: true,
6666
textBreakStrategy: true,
67+
onTextLayout: true,
68+
},
69+
directEventTypes: {
70+
topTextLayout: {
71+
registrationName: 'onTextLayout',
72+
},
6773
},
6874
uiViewClassName: 'RCTText',
6975
};

Libraries/Text/Text/RCTTextShadowView.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
1919
@property (nonatomic, assign) NSLineBreakMode lineBreakMode;
2020
@property (nonatomic, assign) BOOL adjustsFontSizeToFit;
2121
@property (nonatomic, assign) CGFloat minimumFontScale;
22+
@property (nonatomic, copy) RCTDirectEventBlock onTextLayout;
2223

2324
- (void)uiManagerWillPerformMounting;
2425

Libraries/Text/Text/RCTTextShadowView.m

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,35 @@ - (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
306306
[shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext];
307307
}
308308
];
309+
310+
311+
if (_onTextLayout) {
312+
NSMutableArray *lineData = [NSMutableArray new];
313+
[layoutManager
314+
enumerateLineFragmentsForGlyphRange:glyphRange
315+
usingBlock:^(CGRect overallRect, CGRect usedRect, NSTextContainer * _Nonnull usedTextContainer, NSRange lineGlyphRange, BOOL * _Nonnull stop) {
316+
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange actualGlyphRange:nil];
317+
NSString *renderedString = [textStorage.string substringWithRange:range];
318+
UIFont *font = [[textStorage attributedSubstringFromRange:range] attribute:NSFontAttributeName atIndex:0 effectiveRange:nil];
319+
[lineData addObject:
320+
@{
321+
@"text": renderedString,
322+
@"x": @(usedRect.origin.x),
323+
@"y": @(usedRect.origin.y),
324+
@"width": @(usedRect.size.width),
325+
@"height": @(usedRect.size.height),
326+
@"descender": @(-font.descender),
327+
@"capHeight": @(font.capHeight),
328+
@"ascender": @(font.ascender),
329+
@"xHeight": @(font.xHeight),
330+
}];
331+
}];
332+
NSDictionary *payload =
333+
@{
334+
@"lines": lineData,
335+
};
336+
_onTextLayout(payload);
337+
}
309338
}
310339

311340
- (CGFloat)lastBaselineForSize:(CGSize)size

Libraries/Text/Text/RCTTextView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
#import <React/RCTComponent.h>
9+
810
#import <UIKit/UIKit.h>
911

1012
NS_ASSUME_NONNULL_BEGIN

Libraries/Text/Text/RCTTextViewManager.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ @implementation RCTTextViewManager
3434
RCT_REMAP_SHADOW_PROPERTY(adjustsFontSizeToFit, adjustsFontSizeToFit, BOOL)
3535
RCT_REMAP_SHADOW_PROPERTY(minimumFontScale, minimumFontScale, CGFloat)
3636

37+
RCT_EXPORT_SHADOW_PROPERTY(onTextLayout, RCTDirectEventBlock)
38+
3739
RCT_EXPORT_VIEW_PROPERTY(selectable, BOOL)
3840

3941
- (void)setBridge:(RCTBridge *)bridge

0 commit comments

Comments
 (0)