教你如何實現ReactNative字體大小不隨系統字體大小變化而變化


教你如何實現ReactNative字體大小不隨系統字體大小變化而變化


引言

在開發react-nativeApp時,相信大家都應該遇到過這樣的問題:用戶設置了系統的字體大小之後,導致自己的APP佈局紊亂,甚至有些內容會被切掉/隱藏,這對於用戶來講,是非常不好的用戶體驗。

那為什麼會出現這種情況呢呢?原因是我們在開發的時候,佈局的前提是系統的字體大小設置為默認大小,所以只能保證在系統字體大小正常的情況下,我們的佈局是友好的,

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

轉載鏈接:https://www.jianshu.com/p/d2f9ce14127a

Text和TextInput

在react-native中用來顯示文字的,一般會用到兩個組件:Text和TextInput。所以,我們只要針對這兩個組件做好工作,那就基本上解決了字體大小適配的問題

Text和TextInput它們有一個共同屬性:

allowFontScaling

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

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

意思是:

是否隨系統指定的文字大小變化而變化。默認值為true

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

設置allowFontScaling

我們有幾種方式來設置Text和TextInput的allowFontScaling。第一種:

1. 給Text和TextInput組件設置allowFontScaling = false

<code><text>
<textinput>
/<textinput>/<text>/<code>

這種方案效率很低,需要在每個使用到這兩個組件的地方都加上這個屬性。但是一般這兩個組件的使用率還是很高的,所以這是一個龐大的工作量,而且在開發過程當中,我們也很容易忘記設置它

那麼有沒有更好實現方式呢?當然有,這就是下面講的第二種:

2. 自定義MyText/MyTextInput組件

我們可以自定義一個組件MyText, 然後統一設置allowFontScaling = false屬性,然後在其他需要調用的時候,直接用MyText代替Text。

MyText.js

<code>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>
)
}
}
/<code>

這個方案足夠好了,但是,你仍然可能在某段代碼裡,忘記使用MyText而是直接使用Text,這個時候,問題依然會出現。

那麼,就沒有一種萬無一失的方案嗎?當然有啦,第三種:

3. 重寫Text的render()

是的,我們可以重寫Text的render()方法,讓Text在渲染的時候,設置allowFontScaling = false。這裡,我們需要用到lodash的wrap()方法:

0.56(不包括)版本之前

<code>Text.prototype.render = _.wrap(Text.prototype.render, function (func, ...args) {
let originText = func.apply(this, args)
return React.cloneElement(originText, {allowFontScaling: false})
})
/<code>

注意1: 在react-native版本0.56之前,Text是通過React的createReactClass方式來創建類的,也就是說,是通過javascript的prototype的方式來創建類。所以重寫render方法時,需要通過Text.prototype.render來引用

而在0.56版本,Text改為了es6中extends的實現方式來創建類,所以,需要如下方式來重寫render:

0.56(包括)版本之後

<code>Text.render = _.wrap(Text.render, function (func, ...args) {
let originText = func.apply(this, args)
return React.cloneElement(originText, {allowFontScaling: false})
})
/<code>

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

注意2: 這段代碼最好放在你app整個組件執行調用之前,比如在我的項目中,我放的位置:

<code>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>

/<provider>
)
}
}

AppRegistry.registerComponent("xxx", () => MyApp);
/<code>

注意3: 但是很遺憾的是,這個只適用於Text,TextInput不能用於此方案。

那麼,有沒有一種方案,能夠同時兼容Text和TextInput並且做到一勞永逸呢?當然有了,終極方案:

4. 完美方案:修改defaultProps

首先我們來看各種組件的源碼.

TextInput.js

<code>...
getDefaultProps(): Object {
return {
allowFontScaling: true,
underlineColorAndroid: 'transparent',
};
},
...
/<code>

Text.js

<code>...
static defaultProps = {

accessible: true,
allowFontScaling: true,
ellipsizeMode: 'tail',
};
...
/<code>

通過這兩個代碼片段可以知道,在定義Text和TextInput時,都有給組件設置默認屬性的操作.

所以我們可以:

<code>TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, {defaultProps: false})
Text.defaultProps = Object.assign({}, Text.defaultProps, {allowFontScaling: false})
/<code>

來直接設置Text和TextInput的allowFontScaling屬性默認值為false,真正實現了一勞永逸。

確保react-navigation兼容

通過設置defaultProps的方式來修改allowFontScaling的值為false,會有一個問題。

大家在使用react-native時,最常用到的navigator應該是react-navigation。你需要單獨設置headertitleallowfontscaling和allowFontScaling來確保react-navigation的tabTitle和headerTitle沒有問題。

結語

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

我們總結一下:

  1. react-native中使用Text和TextInput負責顯示文字信息
  2. Text和TextInput中設置allowFontScaling=false可以讓字體大小不隨系統設置而變化
  3. 可以通過單個組件設置、自定義組件、重寫render()、設置defaultProps默認值這四種方式來設置allowFontScaling的值為false
  4. 對於重寫render()、設置defaultProps默認值這兩種方式,需要把設置代碼放在app組件初始化之前。
  5. 確保react-navigation兼容


轉載鏈接:https://www.jianshu.com/p/d2f9ce14127a


分享到:


相關文章: