在Web開發中,頁面佈局基於盒子模型,主要經過定位屬性、浮動屬性和顯示屬性實現。而React Native採用的是Flex佈局,但也支持盒子模型的margin、padding以及定位屬性進行佈局。html
以一張圖片來大體瞭解flex佈局的思想react
對於flex各類佈局方式的實現能夠參見這篇文章 移動端全兼容的flexbox速成班 這是移動端web flex佈局,能夠套用思路,只須要將屬性改爲RN的形式就能夠了。web
flex佈局的基本思想是經過flex容器來伸縮控制子項目的寬度和高度。子項目在主軸上依次排列,在側軸上填滿flex容器的可用空間。app
1)用在flex容器上的屬性
① 子項目的排列方向(也就提到不少次的定義主軸):flexDirection: column(default) | row
② 子項目的換行方式(就是超出flex容器跨度時換不換行=。=怎麼換):flexWrap: nowrap(default) | wrap
③ 子項目的對齊方式:justifyContent: flex-start | flex-end | center | space-between | space-around
(主軸)alignItems: flex-start | flex-end | center | stretch(default)
(側軸)
上面屬性的用法和效果都跟Web flex的基本一致,這裏再也不進行演示。iphone
2)用在flex子項上的屬性
單個子項在側軸上的排列方式: alignItems: auto | flex-start | flex-end | center | stretch
移動端web
1)由於RN裏的全部組件都是以flex做爲其顯示屬性,因此不須要再有display:flex
的設定
2)主軸默認方向的區別
在Web Flex中,主軸默認方向是水平的,而在RN是垂直的。
3)支持的屬性和屬性寫法的區別ide
1)文本必須寫在Text中而非View
2)View最好不要嵌套在Text中佈局
在RN中全部的尺寸屬性都是不帶單位的。官網給出的默認單位是dp。
咱們經過Dimensions
這個Api來獲取iphone6模擬器下的設備寬高:flex
console.log('width:'+Dimensions.get('window').width+',height:'+Dimensions.get('window').height);
獲得以下圖結果ui
來看看不一樣iphone下的一些尺寸數值
不難發現咱們這裏得到的寬高正與邏輯分辨率pt對應。因此,對於常規的設計圖,pt和px的轉換規律是pt=dp=px/2
。
1) 屏幕大小
const {devWidth,devHeight} = Dimensions.get('window');
2) dpr
PixelRatio.get()
在Web佈局中,區塊以div包裹,文本以span包裹。默認狀況下div的寬度爲100%屏幕寬度,高爲0。span寬高均爲0。那麼RN中與其用途類似的View和Text組件默認寬高是怎麼定義的呢?
作個實驗:
1)主軸方向垂直
① Text不做爲包裹容器時
<View style={{paddingTop: 18,}}> <Text style={styles.bgcolor_1}>A testing text</Text> <Text style={[styles.bgcolor_2,{width: 200,}]}>A testing text with width was setted</Text> <View style={styles.bgcolor_3}></View> </View>
② Text做爲包裹容器時
<View style={{paddingTop: 18,}}> <Text> <Text style={styles.bgcolor_1}>A testing text</Text> <Text style={[styles.bgcolor_2,{width: 200,}]}>A testing text with width was setted</Text> </Text> //...代碼同上 </View>
2)主軸方向水平
<View style={{paddingTop: 18,flexDirection: 'row'}}> //...代碼同上 </View>
① Text不做爲包裹容器時
② Text做爲包裹容器時
結論:
由上實驗可得,若Text無嵌套,它的顯示方式同View相似。默認狀況下,組件是寬度即爲屏幕寬度,高度爲自身高度(無內容填充則爲0)。若Text中嵌套Text,那麼子組件Text的顯示方式如同Web中的span。
參考官方文檔的定義
<Text>元素在佈局上不一樣於其它組件:在Text內部的元素再也不使用flexbox佈局,而是採用文本佈局。這意味着<Text>內部的元素再也不是一個個矩形,而可能會在行末進行摺疊。
1) numberOfLines佔位問題
一些博文上提到的就算設置了numberOfLines定義最多顯示文本行數,隱藏的文本仍是存在佔位空間。目前這一問題已經修復,能夠放心使用。
<Text numberOfLines={5} style={styles.textWrapper} > <Text style={{fontSize: 20}}>Title</Text>{'\n'} <Text>In this example, the nested title and body text will inherit the fontFamily from styles.baseText, but the title provides its own additional styles. The title and body will stack on top of each other on account of the literal newlines, numberOfLines is Used to truncate the text with an elipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number.</Text> </Text>
2) lineHeight的使用方式
在web中爲實現文本垂直居中效果咱們會設定與高度值一樣的lineHeight。
但因爲在Text嵌套時,Text組件的顯示方式與span相似。即不支持寬高定義。而且即便設定了lineHeight也沒法改變文本的垂直對齊方式。(verticalAlign)
<Text numberOfLines={5} style={styles.textWrapper} > <Text style={{fontSize: 20,lineHeight: 50,backgroundColor: 'aliceblue'}}>Title</Text>{'\n'} <Text>In this example, the nested title and body text will inherit the fontFamily from styles.baseText, but the title provides its own additional styles. The title and body will stack on top of each other on account of the literal newlines, numberOfLines is Used to truncate the text with an elipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number.</Text> </Text>
咱們看到另外一詭異的問題是它的兄弟Text也被設定了一樣的lineHeight值。
因此,開發中爲了實現這一效果,咱們可用View將Text進行包裹,在View中設定其justifyContent
屬性(視實際狀況定)
<View style={{height: 50,justifyContent: 'center',backgroundColor: 'aliceblue'}}> <Text style={{fontSize: 20}}>Title</Text> </View>
1) 默認尺寸
加載靜態資源時,圖片的尺寸能夠加載時當即獲得,並正確渲染到佈局中。
加載動態資源時,不少要在App中顯示的圖片並不能在編譯的時候得到,這時的圖片的默認尺寸爲0*0
咱們知道Flex佈局中,子組件的寬高值受到父組件的約束。
而因爲在加載靜態圖時會當即將圖片原尺寸賦予Image組件,所以即便不設定寬高,它也不受到父組件尺寸的約束。
<View style={{paddingTop: 18}}> <Text style={{paddingTop: 5,paddingBottom: 5,backgroundColor: '#a5e0da'}}>React Native</Text> <View style={{height: 200}}> <Image source={require('./image/react.png')} /> </View> </View>
加載動態資源時
所以不管是靜態仍是動態圖,最好都給它設定一個寬高值。對於動態圖,若只設定其中一個值,還能夠經過resizeMode
來進行調整。resizeMode
提供了三個值
看一段代碼,分別修改Image的resizeMode屬性
<View> <Image style={{height: 100}} resizeMode={'cover'} source={{uri:"http://static.open-open.com/lib/uploadImg/20160412/20160412193341_428.png"}} /> </View>
cover: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都大於等於容器視圖的尺寸(若是容器有padding內襯的話,則相應減去)。譯註:這樣圖片徹底覆蓋甚至超出容器,容器中不留任何空白。
contain: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都小於等於容器視圖的尺寸(若是容器有padding內襯的話,則相應減去)。譯註:這樣圖片徹底被包裹在容器中,容器中可能留有空白
stretch: 拉伸圖片且不維持寬高比,直到寬高都恰好填滿容器。
同Web上的使用方式,但不存在margin塌陷的狀況。嵌套的Text不能設置垂直方向上的margin。
RN中元素默認的定位方式是relative
,而且只有「relative
和absolute
兩種定位方式」。若是爲組件加上position:absolute
,它將會以inline的方式渲染在頁面上。而且脫離正常文檔流。也就是視覺上會被後面的組件覆蓋,但不能經過zIndex方式調整。嵌套的Text不可用。