Skip to content

Commit f5537eb

Browse files
fix(ios): center TextInput text when lineHeight > fontSize on Fabric
Summary: Ports the Paper-only fix from facebook#38359 to the Fabric (new arch) path. When `lineHeight` is set larger than the font's intrinsic line height, UIKit anchors glyphs to the bottom of the attributed-string line box, making typed text visually sit too low while the placeholder (which uses a different rendering path) stays correctly centered. The `RCTApplyBaselineOffset` helper that Paper's fix relies on already ships in Fabric (`RCTAttributedTextUtils.mm`) and is invoked for `<Text>` rendering in `RCTTextLayoutManager`, but was never wired into the `<TextInput>` path. This calls it inside `RCTTextInputComponentView._setAttributedString:`. This regression against Paper is tracked in facebook#39145. It has been reported repeatedly for the new architecture (see comments referring back to facebook#38359). Changelog: [IOS] [FIXED] - Center typed TextInput text when lineHeight > fontSize on the new architecture. Test Plan: Added an RN Tester example ("Single-line lineHeight baseline" under TextInput examples) that renders a single-line TextInput at a range of lineHeight values with a fixed fontSize. Before this change, typing into any of these inputs shows text bottom-anchored inside the line box while the placeholder is centered. After this change, typed text centers alongside the placeholder. Related: facebook#38359, facebook#39145
1 parent 6530092 commit f5537eb

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,10 @@ - (void)_restoreTextSelectionAndIgnoreCaretChange:(BOOL)ignore
768768

769769
- (void)_setAttributedString:(NSAttributedString *)attributedString
770770
{
771+
NSMutableAttributedString *mutableAttributedString = [attributedString mutableCopy];
772+
RCTApplyBaselineOffset(mutableAttributedString);
773+
attributedString = mutableAttributedString;
774+
771775
if ([self _textOf:attributedString equals:_backedTextInputView.attributedText]) {
772776
return;
773777
}

packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,38 @@ module.exports = [
11881188
name: 'textStyles',
11891189
render: () => <TextStylesExample />,
11901190
},
1191+
{
1192+
title: 'Single-line lineHeight baseline',
1193+
name: 'lineHeightBaseline',
1194+
description:
1195+
'Regression repro for https://github.com/facebook/react-native/issues/39145. ' +
1196+
'When lineHeight > fontSize on a single-line TextInput, typed text should ' +
1197+
'stay vertically centered. Placeholder centering is already correct; the ' +
1198+
'bug is that typed glyphs anchor to the bottom of the attributed-string ' +
1199+
'line box, appearing visually too low.',
1200+
render: function (): React.Node {
1201+
return (
1202+
<View>
1203+
{[20, 24, 32, 48].map(lineHeight => (
1204+
<WithLabel
1205+
key={lineHeight}
1206+
label={`fontSize: 16, lineHeight: ${lineHeight}`}>
1207+
<ExampleTextInput
1208+
placeholder="placeholder stays centered"
1209+
style={{
1210+
fontSize: 16,
1211+
lineHeight,
1212+
borderColor: '#ccc',
1213+
borderWidth: 1,
1214+
padding: 8,
1215+
}}
1216+
/>
1217+
</WithLabel>
1218+
))}
1219+
</View>
1220+
);
1221+
},
1222+
},
11911223
{
11921224
title: 'showSoftInputOnFocus',
11931225
render: function (): React.Node {

0 commit comments

Comments
 (0)