ReactNative字體大小不隨系統字體大小變化而變化

引言

在開發react-nativeApp時,相信你們都應該遇到過這樣的問題:用戶設置了系統的字體大小以後,致使本身的APP佈局紊亂,甚至有些內容會被切掉/隱藏,這對於用戶來說,是很是很差的用戶體驗。javascript

那爲何會出現這種狀況呢呢?緣由是咱們在開發的時候,佈局的前提是系統的字體大小設置爲默認大小,因此只能保證在系統字體大小正常的狀況下,咱們的佈局是友好的,html

那麼,咱們應該如何解決這個問題呢?今天這篇文章,就給你們介紹幾種解決方案。java

Text和TextInput

react-native中用來顯示文字的,通常會用到兩個組件:TextTextInput。因此,咱們只要針對這兩個組件作好工做,那就基本上解決了字體大小適配的問題react

TextTextInput它們有一個共同屬性:ios

allowFontScalinggit

這個屬性在react-native官方文檔中解釋以下:es6

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

意思是:redux

是否隨系統指定的文字大小變化而變化。默認值爲truereact-native

這給我提供瞭解決方案,只要咱們給TextTextInput的屬性allowFontScaling設置值爲false,那麼文字大小就不會隨系統字體大小的變化而變化。

設置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。這裏,咱們須要用到lodashwrap()方法:

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。你須要單獨設置headertitleallowfontscalingallowFontScaling來確保react-navigationtabTitleheaderTitle沒有問題。

結語

好了,到此,咱們就完美解決了 react-native開發中,字體大小不隨系統字體大小變化而變化 的問題。

咱們總結一下:

  1. react-native中使用TextTextInput負責顯示文字信息
  2. TextTextInput中設置allowFontScaling=false可讓字體大小不隨系統設置而變化
  3. 能夠經過單個組件設置、自定義組件、重寫render()、設置defaultProps默認值這四種方式來設置allowFontScaling的值爲false
  4. 對於重寫render()、設置defaultProps默認值這兩種方式,須要把設置代碼放在app組件初始化以前。
  5. 確保react-navigation兼容
相關文章
相關標籤/搜索