From 68d795f2d1bd0ce01d0c5183a9f82a4f28684e34 Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sat, 8 Jul 2023 19:32:32 +0800 Subject: [PATCH 1/6] avoid changing Text baseline --- .../Libraries/Text/RCTTextAttributes.m | 10 ++++--- .../Text/TextInput/Multiline/RCTUITextView.h | 3 +++ .../Text/TextInput/Multiline/RCTUITextView.m | 9 +++++++ .../RCTBackedTextInputViewProtocol.h | 3 +++ .../TextInput/RCTBaseTextInputShadowView.m | 21 +++++++++++++++ .../Text/TextInput/RCTBaseTextInputView.h | 2 ++ .../Text/TextInput/RCTBaseTextInputView.m | 27 ++++++++++++++++--- .../TextInput/Singleline/RCTUITextField.h | 2 ++ .../TextInput/Singleline/RCTUITextField.m | 16 ++++++++++- 9 files changed, 86 insertions(+), 7 deletions(-) diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.m b/packages/react-native/Libraries/Text/RCTTextAttributes.m index c8323388ce684b..a4de05108f4f36 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.m +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.m @@ -130,9 +130,13 @@ - (NSParagraphStyle *)effectiveParagraphStyle if (!isnan(_lineHeight)) { CGFloat lineHeight = _lineHeight * self.effectiveFontSizeMultiplier; - paragraphStyle.minimumLineHeight = lineHeight; - paragraphStyle.maximumLineHeight = lineHeight; - isParagraphStyleUsed = YES; + + // Text with lineHeight lower than font.lineHeight does not correctly vertically align. + if (lineHeight > self.effectiveFont.lineHeight) { + paragraphStyle.minimumLineHeight = lineHeight; + paragraphStyle.maximumLineHeight = lineHeight; + isParagraphStyleUsed = YES; + } } if (isParagraphStyleUsed) { diff --git a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h index 205f9943262add..b02d7964f76a5d 100644 --- a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h +++ b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.h @@ -27,6 +27,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) BOOL dictationRecognizing; @property (nonatomic, copy, nullable) NSString *placeholder; @property (nonatomic, strong, nullable) UIColor *placeholderColor; +@property (nonatomic, assign) CGRect fragmentViewContainerBounds; +@property (nonatomic, assign) UIEdgeInsets textBorderInsets; +@property (nonatomic, assign) UIControlContentVerticalAlignment contentVerticalAlignment; @property (nonatomic, assign) CGFloat preferredMaxLayoutWidth; diff --git a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m index ce8a77ec6c1275..c23c370662cc97 100644 --- a/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -169,6 +169,15 @@ - (void)paste:(id)sender [super paste:sender]; } +- (void)setTextBorderInsetsAndFrame:(CGRect)bounds textBorderInsets:(UIEdgeInsets)textBorderInsets +{ + _textBorderInsets = textBorderInsets; + + // We apply `borderInsets` as the `RCTUITextView` layout offset. + self.frame = UIEdgeInsetsInsetRect(bounds, textBorderInsets); + [self setNeedsLayout]; +} + // Turn off scroll animation to fix flaky scrolling. // This is only necessary for iOS <= 14. #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < 140000 diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h index a8719ecd4d0165..55b8946c0f664b 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +++ b/packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h @@ -35,6 +35,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) CGFloat zoomScale; @property (nonatomic, assign, readonly) CGPoint contentOffset; @property (nonatomic, assign, readonly) UIEdgeInsets contentInset; +@property (nonatomic, assign) CGRect fragmentViewContainerBounds; +@property (nonatomic, assign) UIControlContentVerticalAlignment contentVerticalAlignment; // This protocol disallows direct access to `selectedTextRange` property because // unwise usage of it can break the `delegate` behavior. So, we always have to @@ -43,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN // If the change was a result of user actions (like typing or touches), we MUST notify the delegate. - (void)setSelectedTextRange:(nullable UITextRange *)selectedTextRange NS_UNAVAILABLE; - (void)setSelectedTextRange:(nullable UITextRange *)selectedTextRange notifyDelegate:(BOOL)notifyDelegate; +- (void)setTextBorderInsetsAndFrame:(CGRect)bounds textBorderInsets:(UIEdgeInsets)textBorderInsets; // This protocol disallows direct access to `text` property because // unwise usage of it can break the `attributeText` behavior. diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m index 04d2446f86d9b3..1096221486efdb 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m @@ -177,6 +177,27 @@ - (void)uiManagerWillPerformMounting baseTextInputView.textAttributes = textAttributes; baseTextInputView.reactBorderInsets = borderInsets; + + // The CALayer _UITextLayoutFragmentView does not align correctly + // when adding paragraphStyle.maximumLineHeight to an iOS UITextField (issue #28012). + if (!isnan(textAttributes.lineHeight) && !isnan(textAttributes.effectiveFont.lineHeight)) { + CGFloat effectiveLineHeight = textAttributes.lineHeight * textAttributes.effectiveFontSizeMultiplier; + CGFloat fontLineHeight = textAttributes.effectiveFont.lineHeight; + if (effectiveLineHeight >= fontLineHeight * 2.0) { + CGFloat height = self.layoutMetrics.frame.size.height; + CGFloat width = self.layoutMetrics.frame.size.width; + + // Setting contentVerticalAlignment to UIControlContentVerticalAlignmentTop aligns + // _UITextLayoutFragmentView and UITextField on the same ordinate (y coordinate). + baseTextInputView.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; + + // Align vertically _UITextLayoutFragmentView in the center of the UITextField (TextInput). + CGFloat padding = (height - effectiveLineHeight) / 2.0; + baseTextInputView.fragmentViewContainerBounds = CGRectMake(0, padding, width, effectiveLineHeight); + } + } else { + baseTextInputView.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; + } baseTextInputView.reactPaddingInsets = paddingInsets; if (newAttributedText) { diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.h b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.h index 209947de9b4aaa..7258c36e1d8b8f 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.h +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.h @@ -31,6 +31,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) RCTTextAttributes *textAttributes; @property (nonatomic, assign) UIEdgeInsets reactPaddingInsets; @property (nonatomic, assign) UIEdgeInsets reactBorderInsets; +@property (nonatomic, assign) CGRect fragmentViewContainerBounds; +@property (nonatomic, assign) UIControlContentVerticalAlignment contentVerticalAlignment; @property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange; @property (nonatomic, copy, nullable) RCTDirectEventBlock onSelectionChange; diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index cb293db64411b4..4cb40ada22ac93 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -73,9 +73,31 @@ - (void)enforceTextAttributesIfNeeded [textAttributes setValue:[UIColor blackColor] forKey:NSForegroundColorAttributeName]; } + UIFont *font = [textAttributes valueForKey:NSFontAttributeName]; + NSParagraphStyle *paragraphStyle = [textAttributes valueForKey:NSParagraphStyleAttributeName]; + if (paragraphStyle != nil && font != nil && !isnan(paragraphStyle.maximumLineHeight) && paragraphStyle.maximumLineHeight >= font.lineHeight) { + CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; + [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; + } backedTextInputView.defaultTextAttributes = textAttributes; } +// Fixes iOS alignment issue caused by adding paragraphStyle.maximumLineHeight to an iOS UITextField +// and vertically aligns _UITextLayoutFragmentView with the parent view UITextField. +- (void)setContentVerticalAlignment:(UIControlContentVerticalAlignment)contentVerticalAlignment +{ + _contentVerticalAlignment = contentVerticalAlignment; + self.backedTextInputView.contentVerticalAlignment = contentVerticalAlignment; +} + +// Custom bounds used to control vertical position of CALayer _UITextLayoutFragmentView. +// _UITextLayoutFragmentView is the CALayer of UITextField. +- (void)setFragmentViewContainerBounds:(CGRect)fragmentViewContainerBounds +{ + _fragmentViewContainerBounds = fragmentViewContainerBounds; + self.backedTextInputView.fragmentViewContainerBounds = fragmentViewContainerBounds; +} + - (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets { _reactPaddingInsets = reactPaddingInsets; @@ -87,9 +109,8 @@ - (void)setReactPaddingInsets:(UIEdgeInsets)reactPaddingInsets - (void)setReactBorderInsets:(UIEdgeInsets)reactBorderInsets { _reactBorderInsets = reactBorderInsets; - // We apply `borderInsets` as `backedTextInputView` layout offset. - self.backedTextInputView.frame = UIEdgeInsetsInsetRect(self.bounds, reactBorderInsets); - [self setNeedsLayout]; + // Borders are added using insets (UITextField textRectForBound, UITextView setFrame). + [self.backedTextInputView setTextBorderInsetsAndFrame:self.bounds textBorderInsets:reactBorderInsets]; } - (NSAttributedString *)attributedText diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h index 91f8eb087acf87..b581589f1dfcb1 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h @@ -27,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) BOOL dictationRecognizing; @property (nonatomic, strong, nullable) UIColor *placeholderColor; @property (nonatomic, assign) UIEdgeInsets textContainerInset; +@property (nonatomic, assign) CGRect fragmentViewContainerBounds; +@property (nonatomic, assign) UIEdgeInsets textBorderInsets; @property (nonatomic, assign, getter=isEditable) BOOL editable; @property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewID; diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m index 4d0afd97ae682a..f5c29810647ac4 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m @@ -55,6 +55,12 @@ - (void)setTextContainerInset:(UIEdgeInsets)textContainerInset [self setNeedsLayout]; } +- (void)setTextBorderInsetsAndFrame:(CGRect)bounds textBorderInsets:(UIEdgeInsets)textBorderInsets +{ + _textBorderInsets = textBorderInsets; + [self setNeedsLayout]; +} + - (void)setPlaceholder:(NSString *)placeholder { [super setPlaceholder:placeholder]; @@ -170,7 +176,15 @@ - (CGRect)caretRectForPosition:(UITextPosition *)position - (CGRect)textRectForBounds:(CGRect)bounds { - return UIEdgeInsetsInsetRect([super textRectForBounds:bounds], _textContainerInset); + // Text is vertically aligned to the center. + CGFloat leftPadding = _textContainerInset.left + _textBorderInsets.left; + CGFloat rightPadding = _textContainerInset.right + _textBorderInsets.right; + UIEdgeInsets borderAndPaddingInsets = UIEdgeInsetsMake(_textContainerInset.top, leftPadding, _textContainerInset.bottom, rightPadding); + + // The fragmentViewContainerBounds set the correct y coordinates for + // _UITextLayoutFragmentView to fix an iOS UITextField issue with lineHeight. + CGRect updatedBounds = self.fragmentViewContainerBounds.size.height > 0 ? self.fragmentViewContainerBounds : bounds; + return UIEdgeInsetsInsetRect([super textRectForBounds:updatedBounds], borderAndPaddingInsets); } - (CGRect)editingRectForBounds:(CGRect)bounds From e2b615af56aecb93617de8036dff644ef2c3fcda Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sat, 8 Jul 2023 21:19:18 +0800 Subject: [PATCH 2/6] remove logic that over-rides Text lineHeight when fontSize.lineHeight > lineHeight --- .../react-native/Libraries/Text/RCTTextAttributes.m | 10 +++------- .../Libraries/Text/TextInput/RCTBaseTextInputView.m | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.m b/packages/react-native/Libraries/Text/RCTTextAttributes.m index a4de05108f4f36..c8323388ce684b 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.m +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.m @@ -130,13 +130,9 @@ - (NSParagraphStyle *)effectiveParagraphStyle if (!isnan(_lineHeight)) { CGFloat lineHeight = _lineHeight * self.effectiveFontSizeMultiplier; - - // Text with lineHeight lower than font.lineHeight does not correctly vertically align. - if (lineHeight > self.effectiveFont.lineHeight) { - paragraphStyle.minimumLineHeight = lineHeight; - paragraphStyle.maximumLineHeight = lineHeight; - isParagraphStyleUsed = YES; - } + paragraphStyle.minimumLineHeight = lineHeight; + paragraphStyle.maximumLineHeight = lineHeight; + isParagraphStyleUsed = YES; } if (isParagraphStyleUsed) { diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index 4cb40ada22ac93..051b8024159a09 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -75,7 +75,7 @@ - (void)enforceTextAttributesIfNeeded UIFont *font = [textAttributes valueForKey:NSFontAttributeName]; NSParagraphStyle *paragraphStyle = [textAttributes valueForKey:NSParagraphStyleAttributeName]; - if (paragraphStyle != nil && font != nil && !isnan(paragraphStyle.maximumLineHeight) && paragraphStyle.maximumLineHeight >= font.lineHeight) { + if (paragraphStyle.maximumLineHeight >= font.lineHeight) { CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; } From d9ef348308476d34be7e1ef5dcb3fda4137c48c2 Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sat, 8 Jul 2023 21:58:30 +0800 Subject: [PATCH 3/6] check for nan --- .../Libraries/Text/TextInput/RCTBaseTextInputShadowView.m | 4 ++-- .../Libraries/Text/TextInput/RCTBaseTextInputView.m | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m index 1096221486efdb..1a548f1539d100 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m @@ -180,9 +180,9 @@ - (void)uiManagerWillPerformMounting // The CALayer _UITextLayoutFragmentView does not align correctly // when adding paragraphStyle.maximumLineHeight to an iOS UITextField (issue #28012). - if (!isnan(textAttributes.lineHeight) && !isnan(textAttributes.effectiveFont.lineHeight)) { + CGFloat fontLineHeight = textAttributes.effectiveFont.lineHeight; + if (!isnan(textAttributes.lineHeight) && !isnan(fontLineHeight) && textAttributes.lineHeight > 0) { CGFloat effectiveLineHeight = textAttributes.lineHeight * textAttributes.effectiveFontSizeMultiplier; - CGFloat fontLineHeight = textAttributes.effectiveFont.lineHeight; if (effectiveLineHeight >= fontLineHeight * 2.0) { CGFloat height = self.layoutMetrics.frame.size.height; CGFloat width = self.layoutMetrics.frame.size.width; diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index 051b8024159a09..3ce429bfc2db67 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -75,7 +75,7 @@ - (void)enforceTextAttributesIfNeeded UIFont *font = [textAttributes valueForKey:NSFontAttributeName]; NSParagraphStyle *paragraphStyle = [textAttributes valueForKey:NSParagraphStyleAttributeName]; - if (paragraphStyle.maximumLineHeight >= font.lineHeight) { + if (!isnan(paragraphStyle.maximumLineHeight) && !isnan(font.lineHeight) && paragraphStyle.maximumLineHeight >= font.lineHeight) { CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; } From 84d7d14dff0a2a1a4c69fbe8e16d4eb3fb883b6d Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sun, 9 Jul 2023 13:37:41 +0800 Subject: [PATCH 4/6] Test lineHeight lower then fontSize.lineHeight --- .../Libraries/Text/TextInput/RCTBaseTextInputView.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index 3ce429bfc2db67..483b2390678aab 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -78,6 +78,11 @@ - (void)enforceTextAttributesIfNeeded if (!isnan(paragraphStyle.maximumLineHeight) && !isnan(font.lineHeight) && paragraphStyle.maximumLineHeight >= font.lineHeight) { CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; + } else if (font.lineHeight > paragraphStyle.maximumLineHeight) { + NSMutableParagraphStyle *newParagraphStyle = [paragraphStyle mutableCopy]; + newParagraphStyle.maximumLineHeight = font.lineHeight; + newParagraphStyle.minimumLineHeight = font.lineHeight; + [textAttributes setValue:newParagraphStyle forKey:NSParagraphStyleAttributeName]; } backedTextInputView.defaultTextAttributes = textAttributes; } From 0adeebb9b919a5e2586f96ad316559a94872aab5 Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sun, 9 Jul 2023 13:43:57 +0800 Subject: [PATCH 5/6] adding comments --- .../Text/TextInput/RCTBaseTextInputView.m | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m index 483b2390678aab..48c005f0877d7a 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -75,14 +75,18 @@ - (void)enforceTextAttributesIfNeeded UIFont *font = [textAttributes valueForKey:NSFontAttributeName]; NSParagraphStyle *paragraphStyle = [textAttributes valueForKey:NSParagraphStyleAttributeName]; - if (!isnan(paragraphStyle.maximumLineHeight) && !isnan(font.lineHeight) && paragraphStyle.maximumLineHeight >= font.lineHeight) { - CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; - [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; - } else if (font.lineHeight > paragraphStyle.maximumLineHeight) { - NSMutableParagraphStyle *newParagraphStyle = [paragraphStyle mutableCopy]; - newParagraphStyle.maximumLineHeight = font.lineHeight; - newParagraphStyle.minimumLineHeight = font.lineHeight; - [textAttributes setValue:newParagraphStyle forKey:NSParagraphStyleAttributeName]; + if (!isnan(paragraphStyle.maximumLineHeight) && !isnan(font.lineHeight)) { + if (paragraphStyle.maximumLineHeight >= font.lineHeight) { + // The baseline aligns the text vertically in the line height (_UITextLayoutFragmentView). + CGFloat baseLineOffset = (paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0; + [textAttributes setValue:@(baseLineOffset) forKey:NSBaselineOffsetAttributeName]; + } else if (font.lineHeight > paragraphStyle.maximumLineHeight) { + // Text with lineHeight lower than font.lineHeight does not correctly vertically align. + NSMutableParagraphStyle *newParagraphStyle = [paragraphStyle mutableCopy]; + newParagraphStyle.maximumLineHeight = font.lineHeight; + newParagraphStyle.minimumLineHeight = font.lineHeight; + [textAttributes setValue:newParagraphStyle forKey:NSParagraphStyleAttributeName]; + } } backedTextInputView.defaultTextAttributes = textAttributes; } From b2e83de437907865fbc4dfa381d720774a9d5b64 Mon Sep 17 00:00:00 2001 From: Fabrizio Bertoglio Date: Sun, 9 Jul 2023 14:01:11 +0800 Subject: [PATCH 6/6] fix internal FB linter issue The diff would trigger linter error internal in Facebook. I compared the commit and the original diff and I was able to identify the linter issue. I fixed the linter issue to avoid again failures when importing it. Comment https://github.com/facebook/react-native/pull/37465#issuecomment-1600505344 Imported in Facebook https://github.com/facebook/react-native/commit/35a1648d0c93ef2db1de6b8dbe7fc1d997c24039#diff-08824b4f7ca9c31bd2a7aeb8b1180bd55b2b834d99667861e14e59082d06c137R179-R190 Original Diff https://github.com/facebook/react-native/pull/37465/commits/c4996fce8b5394882bd35cc8ee827dfaf1321afd#diff-08824b4f7ca9c31bd2a7aeb8b1180bd55b2b834d99667861e14e59082d06c137R170-R177 --- .../Text/TextInput/Singleline/RCTUITextField.m | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m index f5c29810647ac4..09511b293967a1 100644 --- a/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m +++ b/packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.m @@ -179,12 +179,15 @@ - (CGRect)textRectForBounds:(CGRect)bounds // Text is vertically aligned to the center. CGFloat leftPadding = _textContainerInset.left + _textBorderInsets.left; CGFloat rightPadding = _textContainerInset.right + _textBorderInsets.right; - UIEdgeInsets borderAndPaddingInsets = UIEdgeInsetsMake(_textContainerInset.top, leftPadding, _textContainerInset.bottom, rightPadding); - - // The fragmentViewContainerBounds set the correct y coordinates for - // _UITextLayoutFragmentView to fix an iOS UITextField issue with lineHeight. - CGRect updatedBounds = self.fragmentViewContainerBounds.size.height > 0 ? self.fragmentViewContainerBounds : bounds; - return UIEdgeInsetsInsetRect([super textRectForBounds:updatedBounds], borderAndPaddingInsets); + UIEdgeInsets borderAndPaddingInsets = + UIEdgeInsetsMake(_textContainerInset.top, leftPadding, _textContainerInset.bottom, rightPadding); + if (self.fragmentViewContainerBounds.size.height > 0) { + // apply custom bounds to fix iOS UITextField issue with lineHeight + // sets the correct y coordinates for _UITextLayoutFragmentView + return UIEdgeInsetsInsetRect([super textRectForBounds:self.fragmentViewContainerBounds], borderAndPaddingInsets); + } else { + return UIEdgeInsetsInsetRect([super textRectForBounds:bounds], borderAndPaddingInsets); + } } - (CGRect)editingRectForBounds:(CGRect)bounds