前言:
相信和我一样使用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'。
到此,问题就迎刃而解了,是不是特别开心!
如果觉得写的不错,欢迎点赞、收藏、评论哦!