ReactNative字体大小不随系统字体大小变化而变化

栏目: IOS · Android · 发布时间: 7年前

内容简介:在开发那为什么会出现这种情况呢呢?原因是我们在开发的时候,布局的前提是系统的字体大小设置为默认大小,所以只能保证在系统字体大小正常的情况下,我们的布局是友好的,那么,我们应该如何解决这个问题呢?今天这篇文章,就给大家介绍几种解决方案。

在开发 react-native App时,相信大家都应该遇到过这样的问题:用户设置了系统的字体大小之后,导致自己的APP布局紊乱,甚至有些内容会被切掉/隐藏,这对于用户来讲,是非常不好的用户体验。

那为什么会出现这种情况呢呢?原因是我们在开发的时候,布局的前提是系统的字体大小设置为默认大小,所以只能保证在系统字体大小正常的情况下,我们的布局是友好的,

那么,我们应该如何解决这个问题呢?今天这篇文章,就给大家介绍几种解决方案。

Text和TextInput

react-native 中用来显示文字的,一般会用到两个组件: TextTextInput 。所以,我们只要针对这两个组件做好工作,那就基本上解决了字体大小适配的问题

TextTextInput 它们有一个共同属性:

allowFontScaling

这个属性在 react-native 官方文档中解释如下:

Specifies whether fonts should scale to respect Text Size accessibility settings. The default is true .

意思是:

是否随系统指定的文字大小变化而变化。默认值为 true

这给我提供了解决方案,只要我们给 TextTextInput 的属性 allowFontScaling 设置值为 true ,那么文字大小就不会随系统字体大小的变化而变化。

设置allowFontScaling

我们有几种方式来设置 TextTextInputallowFontScaling 。第一种:

1. 给 TextTextInput 组件设置 allowFontScaling = false

<Text allowFontScaling={false}/>
<TextInput allowFontScaling={false}/> 
复制代码

这种方案效率很低,需要在每个使用到这两个组件的地方都加上这个属性。但是一般这两个组件的使用率还是很高的,所以这是一个庞大的工作量,而且在开发过程当中,我们也很容易忘记设置它

那么有没有更好实现方式呢?当然有,这就是下面讲的第二种:

2. 自定义MyText/MyTextInput组件

我们可以自定义一个组件 MyText , 然后统一设置 allowFontScaling = false 属性,然后在其他需要调用的时候,直接用 MyText 代替 Text

MyText.js

import React from 'react'
import {Text} from 'react-native'

export default class MyText extends React.Component {

    render() {
        return (
            <Text
                allowFontScaling={false}
                {...this.props}>
                {this.props.children}
            </Text>
        )
    }
}
复制代码

这个方案足够好了,但是,你仍然可能在某段代码里,忘记使用 MyText 而是直接使用 Text ,这个时候,问题依然会出现。

那么,就没有一种万无一失的方案吗?当然有啦,第三种:

3. 重写Text的render()

是的,我们可以重写 Textrender() 方法,让 Text 在渲染的时候,设置 allowFontScaling = false 。这里,我们需要用到 lodash wrap() 方法:

0.56(不包括)版本之前

Text.prototype.render = _.wrap(Text.prototype.render, function (func, ...args) {
    let originText = func.apply(this, args)
    return React.cloneElement(originText, {allowFontScaling: false})
})
复制代码

注意1: react-native 版本 0.56 之前, Text 是通过React的 createReactClass 方式来创建类的,也就是说,是通过 javascriptprototype 的方式来创建类。所以重写 render 方法时,需要通过 Text.prototype.render 来引用

而在 0.56 版本, Text 改为了 es6extends 的实现方式来创建类,所以,需要如下方式来重写 render

0.56(包括)版本之后

Text.render = _.wrap(Text.render, function (func, ...args) {
    let originText = func.apply(this, args)
    return React.cloneElement(originText, {allowFontScaling: false})
})
复制代码

大家可以查看源码,或者查看 0.56change-log

注意2: 这段代码最好放在你app整个组件执行调用之前,比如在我的项目中,我放的位置:

import React from 'react'
import {AppRegistry, Text, DeviceEventEmitter, YellowBox} from 'react-native'
import {Provider} from 'react-redux'
import App from './src/App'
import _ from 'lodash'


//字体不随系统字体变化
Text.render = _.wrap(Text.render, function (func, ...args) {
    let originText = func.apply(this, args)
    return React.cloneElement(originText, {allowFontScaling: false})
})

...
...

class MyApp extends React.Component {
    render() {
        return (
            <Provider store={store}>
                <App/>
            </Provider>
        )
    }
}

AppRegistry.registerComponent("xxx", () => MyApp);
复制代码

注意3: 但是很遗憾的是,这个只适用于 TextTextInput 不能用于此方案。

那么,有没有一种方案,能够同时兼容 TextTextInput 并且做到一劳永逸呢?当然有了,终极方案:

4. 完美方案:修改defaultProps

首先我们来看各种组件的源码.

TextInput.js

...
  getDefaultProps(): Object {
    return {
      allowFontScaling: true,
      underlineColorAndroid: 'transparent',
    };
  },
...
复制代码

Text.js

...
  static defaultProps = {
    accessible: true,
    allowFontScaling: true,
    ellipsizeMode: 'tail',
  };
...
复制代码

通过这两个代码片段可以知道,在定义 TextTextInput 时,都有给组件设置默认属性的操作.

所以我们可以:

TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, {defaultProps: false})
Text.defaultProps = Object.assign({}, Text.defaultProps, {allowFontScaling: false})
复制代码

来直接设置 TextTextInputallowFontScaling 属性默认值为 false ,真正实现了一劳永逸。

确保react-navigation兼容

通过设置 defaultProps 的方式来修改 allowFontScaling 的值为 false ,会有一个问题。

大家在使用 react-native 时,最常用到的 navigator 应该是 react-navigation 。你需要单独设置 headertitleallowfontscaling 和allowFontScaling来确保 react-navigationtabTitleheaderTitle 没有问题。

结语

好了,到此,我们就完美解决了* react-native 开发中,字体大小不随系统字体大小变化而变化*的问题。

我们总结一下:

  1. react-native 中使用 TextTextInput 负责显示文字信息
  2. TextTextInput 中设置 allowFontScaling=false 可以让字体大小不随系统设置而变化
  3. 可以通过单个组件设置、自定义组件、重写 render() 、设置 defaultProps 默认值这四种方式来设置 allowFontScaling 的值为 false
  4. 对于重写 render() 、设置 defaultProps 默认值这两种方式,需要把设置代码放在app组件初始化之前。
  5. 确保 react-navigation 兼容

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Geometric Folding Algorithms

Geometric Folding Algorithms

Erik D Demaine / Cambridge University Press / 2008-8-21 / GBP 35.99

Did you know that any straight-line drawing on paper can be folded so that the complete drawing can be cut out with one straight scissors cut? That there is a planar linkage that can trace out any alg......一起来看看 《Geometric Folding Algorithms》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具