如何在 React Native 中处理 Android 手机吞字问题
本文由 AI 协助更新
React Native App 在部分型号的 Android 手机上,可能会发生文字显示不全的问题。
2026-02-09 更新:重写 Text.render 的方式在高版本 ReactNative 已无效
下面采用 Babel 别名 + Proxy + Shim 组件 的方式,在任意 RN 版本下都能无侵入地修复该问题。
复现问题
作者在 React Native 0.67.4 环境下,编写了一个小 demo 来复现这个问题,如下:
function IncompleteText() {
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.text}>我在左边 完整</Text>
<Text style={styles.text}>我在右边 完整</Text>
</View>
<View style={styles.row}>
<Text style={styles.text}>12345</Text>
<Text style={styles.text}>67890</Text>
</View>
<View style={styles.row}>
<Text style={styles.text}>abcd</Text>
<Text style={styles.text}>efgh</Text>
</View>
<View style={styles.row}>
<Text style={styles.text}>今年是 2022 年</Text>
<Text style={styles.text}>亏了好多 ¥</Text>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
row: {
marginTop: 16,
marginHorizontal: 24,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
height: 60,
backgroundColor: '#f5f5f5',
},
text: {
fontSize: 18,
color: '#333333',
fontWeight: 'normal',
// fontFamily: 'DFWaWaSC-W5',
backgroundColor: 'yellow',
},
})
当 Text 中的文本同时符合以下两个条件时,在部分 Android 手机上会出现文字显示不全的问题。
- 含有半角字符(数字、字母、空格、特殊符号)
- style 设置了
fontWeight属性,不管它的值是什么
譬如作者这台手机:
| 手机型号 | MIUI 版本 | Android 版本 |
|---|---|---|
| MI 8 | 12.5.2 | 10 |
就会出现文字显示不全的问题,即使将 fontWeight 设置为 bold,也不会有粗体效果。

但是只要 style 设置了 fontFamily,就不会有显示不全的问题,因此,怎样才能正确地设置 fontFamily 呢?
解决问题
思路:用 Babel 的 module-resolver 把对 react-native 的引用指到我们自己的 proxy 文件;proxy 对 Text(以及可选的 View、Image 等)返回 Shim 组件,Shim 内部再使用真实的 react-native 并注入默认 fontFamily。这样不依赖 RN 内部 Text.render,兼容从低版本到高版本的所有 RN。
1. 安装依赖
本方案依赖 Babel 的 module-resolver 插件做别名解析,需先安装(若已为其他 Shim 配过可跳过):
yarn add -D babel-plugin-module-resolver
2. Babel 配置
在 babel.config.js 的 module-resolver 里为 react-native 配置别名,指向项目中的 proxy 文件(路径按你项目结构调整,例如放在 app/utils/ 下):
// babel.config.js
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./'],
extensions: ['.ts', '.tsx', '.ios.js', '.android.js', '.js', '.json'],
alias: {
'^react-native$': './app/utils/react-native-proxy.js', // 指向下面的 proxy 文件
// ... 其他 alias
},
},
],
],
};
3. react-native-proxy.js
从真实 react-native 包做一层 Proxy,对 Text 返回我们的 TextShim,其余组件直接透传。这样业务里 import { Text } from 'react-native' 拿到的就是 Shim。
// app/utils/react-native-proxy.js(路径需与 babel alias 一致)
const RN = require('../../node_modules/react-native');
module.exports = new Proxy(RN, {
get(target, prop) {
if (prop === 'Text') {
if (!module.exports.__TextShim) {
module.exports.__TextShim = require('./shim/TextShim').default;
}
return module.exports.__TextShim;
}
return target[prop];
},
});
若已按 无侵入增强 React Native 组件方案 配置了 proxy,可在此 proxy 里一起代理 View、Image 等,同一套 proxy 即可。
4. TextShim 组件(解决吞字)
Shim 内只对 Android 合并默认 fontFamily,其它平台直接使用原生 Text。
// app/utils/shim/TextShim.tsx
import React from 'react';
import type { TextProps } from 'react-native';
const RN = require('../../node_modules/react-native');
const defaultFontFamily = {
...RN.Platform.select({
android: { fontFamily: '' },
}),
};
const TextShim = (props: TextProps) => {
const { style, ...rest } = props;
if (RN.Platform.OS !== 'android') {
return <RN.Text style={style} {...rest} />;
}
const flat = RN.StyleSheet.flatten(style) || {};
return <RN.Text style={[defaultFontFamily, flat]} {...rest} />;
};
export default TextShim;
按需可在此 Shim 里再做 fontWeight → fontFamily 的映射(例如项目中的 shim/font-helpers.ts),以同时解决粗体与吞字。
示例
这里有一个示例,供你参考。