攻克小米10等机型文字截断问题:React Native优雅适配部分安卓机型文字显示不全策略

使用react-native开发app会遇到兼容问题,如小米10等部分机型<Text>组件文字显示不全。作者总结了四种解决方法,包括追加空格、写自定义Text等,还提出处理思路,但现有方法存在性能影响、样式覆盖不可控等问题,推荐重新写文本组件的新思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

相信和我一样使用react-native开发app的猿友,都会遇到很多兼容问题。那么大家有没有遇到过小米10及其他部分机型出现<Text></Text>组件中的文字 显示不全(结尾的文字 不显示)的问题。这个问题困扰了我很久,根据时间的推移,将解决方案做了总结。

废话少说,直接上干货。

解决方法:

我尝试过四种解决方法:这里用的reactnative版本是0.77.1

第一种:(太low)

这是一种笨办法,在每个<Text>内容  </Text>中的文字后面多追加一个 空格,来填补显示不全的位置。

<Text>我有5个字 </Text>

此方法虽然可以解决问题,但却比较繁琐,不利于维护。

第二种:写一个自定义Text

interface CtProps {
    text: TextProps;
    style?: any;
}
const CustomText:React.FC<CtProps > =({text,style})=>{
    <RnText style={style}>{text} </RnText> // 这里的关键是加空格
}
export default CustomText;

第三种:(很遗憾的跟猿友们汇报,reactnative0.66版本以前是奏效的,0.66以后则不起作用,请使用第四种)

在react-native的入口页App.js增加覆盖渲染如下:

  const defaultFontFamily = {
    ...Platform.select({
      android: { fontFamily: ' ' },
    }),
  };
const oldRender = Text.render;
Text.render = function (...args) {
  const origin = oldRender.call(this, ...args);
  return React.cloneElement(origin, {
    style: [defaultFontFamily, origin.props.style],
  });
};
第四种:(设置具体的字体serif,虽然可以解决问题,但是客户看上去视觉体验不是特别好,还在继续寻找更完美的解决方案)

在入口页设置字体覆盖渲染 如何:

  
 import DeviceInfo from 'react-native-device-info';

 const brand = deviceInfo.getBrand()?.toLowerCase();
 const familyStyle= ()=>{
    let style = {};
     if (brand && brand.includes('xiaomi')) {
           style = { fontFamily: 'serif'};
     }
     return style
 }
const defaultFontFamily = {
    ...Platform.select({
      android: familyStyle(), // 只改了这里,并且只有这个字体正常不缺失,但是字体对客户来说体验不是特别友好
    }),
  };
const oldRender = Text.render;
Text.render = function (...args) {
  const origin = oldRender.call(this, ...args);
  return React.cloneElement(origin, {
    style: [defaultFontFamily, origin.props.style],
  });
};
思路:

这个问题主要是由于小米或其他手机厂商自己定义的字体的兼容性问题,我们这里的处理思路是:

强制所有 <Text> 组件在 Android 平台上使用系统默认字体,通过(猴子补丁)劫持Text.render 方法,在渲染时注入默认字体样式。

  • oldRender.call: 先执行原始渲染逻辑
  • React.cloneElement: 克隆生成的元素并添加新样式
  • 样式合并规则:defaultFontFamily 会覆盖组件自身的 fontFamily 设置
问题思考:

以上方法虽能解决问题,但存在问题:

  • 性能影响

    • 每次 Text 渲染都会多一次 cloneElement 操作

    • 对于复杂界面可能有性能损耗

  • 样式覆盖不可控

    • 会强制覆盖所有 Text 的自定义字体设置

    • 如果某些页面需要特殊字体,需要额外处理

  • TypeScript 类型错误

    • 直接修改 Text.render 可能导致类型检查失败

新思路一:

判断有问题的机型才执行此操作,这样即使有性能问题,也只会影响有限机型。

新思路二:

重新写一个文本组件

  const defaultFontFamily = {
    ...Platform.select({
      android: { fontFamily: ' ' },
    }),
  };
const DefaultText = (props) => (
  <Text {...props} style={[defaultFontFamily, props.style]} />
);

// 使用示例
<DefaultText>所有文本自动应用默认字体</DefaultText>

新思路二,是我比较推荐的解决方案,既可解决问题,又不存在性能问题,可谓一举两得。如果有合适的自定义字体文件,如xx.ttf,可更改为fontFamily='xx.ttf'。

到此,问题就迎刃而解了,是不是特别开心!

如果觉得写的不错,欢迎点赞、收藏、评论哦!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老猿阿浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值