You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:45:05