React Native iOS TextInput 系统字体调小时20行左右光标与文字消失问题
React Native iOS多行TextInput系统字体缩小后第20行光标消失解决方案
根因说明
该问题由iOS端React Native多行TextInput的内容高度计算逻辑缺陷导致:当关闭TextInput自身滚动、由外部ScrollView承载内容,同时系统字体缩放比例变化时,TextInput内置的内容高度计算会出现固定偏移误差,当内容行数达到阈值时就会出现光标偏移出可视区域、内容临时被截断的情况。
具体修复步骤
- 修正现有代码的样式绑定疏漏:你定义的
MyTextInput样式未绑定到TextInput组件上,首先补充样式绑定。 - 动态适配系统字体缩放的字体大小和行高,不要写死固定像素值,同时开启字体缩放支持:
import { useState } from 'react'; import { PixelRatio } from 'react-native'; // 基础配置可按设计稿调整 const BASE_FONT_SIZE = 16; const LINE_HEIGHT_MULTIPLE = 1.625; // 对应原16px字号下26px行高的比例 const fontScale = PixelRatio.getFontScale(); const dynamicFontSize = BASE_FONT_SIZE * fontScale; const dynamicLineHeight = dynamicFontSize * LINE_HEIGHT_MULTIPLE;
- 监听TextInput内容高度变化,动态更新组件高度,避免内置计算误差:
const [inputHeight, setInputHeight] = useState(dynamicLineHeight * 5); // 初始高度对应numberOfLines={5}
- 给TextInput补充iOS专属适配属性,规避系统默认交互的高度计算干扰
修复后完整代码示例
import { useState, useRef } from 'react'; import { PixelRatio, ScrollView, View } from 'react-native'; import styled from 'styled-components/native'; const BASE_FONT_SIZE = 16; const LINE_HEIGHT_MULTIPLE = 1.625; const fontScale = PixelRatio.getFontScale(); const dynamicFontSize = BASE_FONT_SIZE * fontScale; const dynamicLineHeight = dynamicFontSize * LINE_HEIGHT_MULTIPLE; const Container = styled.View` flex: 1; margin-bottom: 8px; `; const MyTextInput = styled.TextInput` line-height: ${dynamicLineHeight}px; padding: 0 32px 16px; font-size: ${dynamicFontSize}px; text-align-vertical: top; `; export default function LongTextForm() { const [value, setValue] = useState(''); const [inputHeight, setInputHeight] = useState(dynamicLineHeight * 5); const scrollRef = useRef(null); const placeholder = '请输入内容'; const onFocus = () => { // 原有焦点逻辑保留 }; return ( <Container> <ScrollView ref={scrollRef} style={{ flex: 1 }} keyboardShouldPersistTaps="always" contentInset={{ bottom: 260 }} > <View style={{ flex: 1 }}> <MyTextInput autoFocus multiline onFocus={onFocus} numberOfLines={5} scrollEnabled={false} placeholder={placeholder} value={value} onChangeText={setValue} allowFontScaling={true} onContentSizeChange={(e) => { const newHeight = e.nativeEvent.contentSize.height; // 避免频繁跳动,加1px容错阈值 if (Math.abs(newHeight - inputHeight) > 1) { setInputHeight(newHeight); } }} style={{ height: inputHeight }} automaticallyAdjustsScrollIndicatorInsets={false} disableFullscreenUI={true} /> </View> </ScrollView> </Container> ); }
额外注意事项
- 如果还是出现偶发的光标偏移,可以给TextInput加
selection={{ start: value.length, end: value.length }}手动控制光标位置。 - 不要给TextInput外层的View加多余的padding或者margin,避免高度计算叠加误差。
内容的提问来源于stack exchange,提问作者Ryota Shintani
相关产品推荐
相关产品推荐

