很多人在做布局的時候描馅,發(fā)現(xiàn)Text的寬高不好測量营勤,布局不好處理富弦,現(xiàn)我將方法和RN的相關源碼列出來沟娱,供大家參考:
1、測量Text的寬高
? ? 1.1? 方法一 :onLayout
? ? 首先在view中有個onLayout方法腕柜,這里面攜帶的就有寬高信息:
代碼如下:
<Text onLayout={({nativeEvent:e})=>this.layout(e)}></Text>
layout=(e)=>{ ?console.log(e)??}
nativeEvent里面的內容大家可以看到济似,
x和y表示左上角的頂點坐標,相對于整個屏幕的左上角(0盏缤,0)砰蠢;
height和width就是這個text的寬高,
target則是這個Text的ReactTag的標簽唉铜,這里是5台舱,也就是說每一個React組件都會有一個tag值,而且是唯一的潭流,簡單的理解就是能找到這個組件標簽竞惋。
至于為什么這個值是5,下面會講解:
? ? 1.2 ?方法二?:measure
我們還有一種方法灰嫉,直接用react標簽的measure方法拆宛,代碼如下:
然后我們在componentDidMount方法里面添加一個定時器,定時器里面再進行測量讼撒,代碼如下:
如果不用定時器的話浑厚,會出現(xiàn)測量的結果為0股耽,加個定時器就可以正常測出時間了寬高了,我還是建議用第一種方法onLayout方法進行測量钳幅,第二種方法還要在componentWillUnmount卸載定時器
2物蝙、AppRegistry
?在android的view繪制過程中,有三個方法按照先后順序執(zhí)行贡这,onMeasure-->onLayout-->onDraw茬末,只要自定義過View的童鞋我相信都知道,而React Native的渲染繪制是從注冊組件開始的盖矫,也就是AppRegistry丽惭。
每次在調試的時間,大家在瀏覽器中總會看到如下的打印信息:
這段信息就是RN的開始吧辈双,先找到根View责掏,這段打印的信息是在AppRegistry的runApplication方法中的,
runApplication: function(appKey: string, appParameters: any): void {
? const msg =
? ? 'Running application "' + appKey + '" with appParams: ' +
? ? JSON.stringify(appParameters) + '. ' +
? ? '__DEV__ === ' + String(__DEV__) +
? ? ', development-level warning are ' + (__DEV__ ? 'ON' : 'OFF') +
? ? ', performance optimizations are ' + (__DEV__ ? 'OFF' : 'ON');
? infoLog(msg);
? BugReporting.addSource('AppRegistry.runApplication' + runCount++, () => msg);
? invariant(
? ? runnables[appKey] && runnables[appKey].run,
? ? 'Application ' + appKey + ' has not been registered. This ' +
? ? 'is either due to a require() error during initialization ' +
? ? 'or failure to call AppRegistry.registerComponent.'
? ? );
? runnables[appKey].run(appParameters);
?},
3湃望、renderApplication
這里面就是渲染了根組件
這個RootComponent的tag值是1换衬,
下面就是AppContainer
4、AppContainer
React native里面就用了3個tag了证芭,所以你自己的組件的target也就是從4開始的瞳浦,我的Text外面還包了一層view,這層view的tag值是4废士,Text就是5了叫潦,這就回答了1中的問題。
5官硝、measure
1中的寬高和其實位置信心其實在測量的時間就已經(jīng)定下來了矗蕊,也就是UIManager的measure方法,大家可以反過來再調用下這個方法氢架;
首先引用下這個UIManager
var UIManager = require('UIManager');
layout=(e)=>{
? ? console.log(e)
? ? UIManager.measure(e.target, (x, y, width, height, left, top) => {
? ? ? ? console.log('x:'+x)
? ? ? ? console.log('y:'+y)
? ? ? ? console.log('width:'+width)
? ? ? ? console.log('height:'+height)
? ? ? ? console.log('left:'+left)
? ? ? ? console.log('top:'+top)
? ? })
?}?
然后在layout的方法中加入這個measure方法就行了傻咖,這個方法有兩個參數(shù),第一個就是上面講的reacttag值岖研,第二個是個callback方法卿操,這個方法里面就是寬高和位置信息,其實還有個onError的callback的方法缎玫,但是Native bridge還沒有surface的錯誤硬纤。
源代碼如下:
function(
? ? tag: ?number,
? ? onError: OnErrorCallback,
? ? onSuccess: OnSuccessCallback
? ? ): void {
? ? ? ? if (tag == null) {
? ? ? ? ? ? return;
? ? ? ? }
? ? UIManager.measure(??tag,?onSuccess?? );
? ? };
而success的callback方法代碼如下,錯誤的callback是個空函數(shù):
type OnSuccessCallback = (
? ? left: number,
? ? top: number,
? ? width: number,
? ? height: number,
? ? pageX: number,
? ? pageY: number
?) => void
大家可以看出measure的x赃磨、y和left筝家、top的值是一樣的,寬高和onLayout方法的寬高是一樣的邻辉。
6溪王、實際機型測試對比
以上對應的都是手機設置顯示的標準字體腮鞍,其他大小的字體沒有測試,另外我的漢字測試的是中文文字移国,英文文字、數(shù)字的寬高是不一樣的迹缀,另外字體會有一定的內邊距,大家把字體的fontsize改成100祝懂,單獨看一個字就可以看出來,這里為了統(tǒng)一得到字體的寬高就用onlayout的nativeEvent方法就可以了