RN中的佈局我以爲主要包含這幾個部分:像素單位,佈局方式,組件,CSS。熟悉這幾點後,就是經驗的積累,見得多了作的多了佈局代碼寫起來天然就快許多。 html
react native 的頁面佈局使用的是flex佈局,Flex是Flexible Box的縮寫,意爲"彈性佈局",用來爲盒狀模型提供最大的靈活性。flex只是一種元素佈局方式,因此任何一個元素均可以設定flex,而一個元素設定了flex以後,那麼它裏面的全部元素都是在這個容器內佈局。react
在RN中的flex佈局跟web中略有不一樣,RN中flex只能夠指定一個數字, 根據具體數字值來填充展現當前元素,「1」即表示100%撐滿當前容器,而該容器內的子元素只可以在該容器內區域佈局。ios
2. 主次軸web
容器內默認有兩根軸,橫軸和縱軸,當畫一個頁面時,首先要肯定該頁面或者該容器內是採用哪一個軸做爲主軸佈局,其實就是行佈局或者列布局。當肯定主軸以後,另一軸自動成爲副軸。RN中使用flexDirection來定義當前容器是使用何種佈局(column活row),默認爲column。justifyContent 和 alignItems 分別制定主軸和次軸的排列方式。ide
flexDirection: column;row;佈局
justifyContent:flex
flex-start(默認,起始位置,通常都是左對齊);flexbox
center(居中);spa
flex-end(結尾,通常是右對齊);code
space-around;space-between;
alignItems:
flex-start(默認,起始位置,通常都是左對齊);
center(居中);
flex-end(結尾,通常是右對齊);
stretch(均勻分佈);
當父容器指定了flex以後(好比1),那麼若是子元素的flex也都設置爲1,那麼這些子元素將會平均分配父容器的尺寸來佈局,就像以下代碼:
<View style={{flex:1,flexDirection:'row',backgroundColor:'#ffffff'}}> <View style={{flex:1,backgroundColor:'red'}}></View> <View style={{flex:1,backgroundColor:'black'}}></View> <View style={{flex:1,backgroundColor:'blue'}}></View> </View>
![]() |
|
flexDirection:'column' | flexDirection:'row' |
再舉個例子,子元素指定寬高,父容器採用space-between 和 space-around佈局,代碼以下:
<View style={{flex:1,borderWidth:2,flexDirection:'column',backgroundColor:'#ffffff',justifyContent:'space-between', alignItems:'center'}}> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'red'}}></View> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'black'}}></View> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'blue'}}></View> </View>
![]()
|
![]()
|
justifyContent:'space-between' | justifyContent:'space-around' |
下面實現一個具體的例子,效果以下:
這是一個表單頁面,從這個圖能夠得出:
1. 外層是主軸按照column排列。行元素撐滿一行。
2. 行元素高度固定,主軸按row排列,次軸的排列應該居中。
3. 行元素有內襯,有分割線。
4. 行元素內應該分左右兩部分,分別左右對齊。
根據這幾點,咱們能夠大概寫出這樣的佈局:
class Layout extends Component { render() { return ( <View style={{flex:1,backgroundColor:'#dddddd',flexDirection:'column',justifyContent:'center'}}> <View style={LayoutStyles.row}> <Text style={{flex:1}}>真實姓名</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>John</Text> </View> </View> <View style={LayoutStyles.row}> <Text>手機號碼</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>13812345678</Text> </View> </View> </View> ); } } const LayoutStyles = StyleSheet.create({ row: { backgroundColor:'#ffffff', height:47, flexDirection:'row', alignItems:'center', borderBottomWidth:0.5, borderBottomColor:'#dddddd', paddingHorizontal: 15 } });
這裏能夠看到, 在「手機號碼」這一行內,用兩個子元素Text和View分別設置flex:1來撐滿行元素,而後設置view的末端對齊。
而「真實姓名」這一行只對view設置了flex:1,也達到了這個效果。
經過給view加上border看一下:
能夠看出,若是在一個容器內,若是元素沒有設置flex,那麼默認會根據該元素的內容自動撐開寬度,而設置了flex:1的元素則會佔滿剩餘的空間。
那麼這裏給 「真實姓名」這行的右邊部分留下較大的空間,由於這裏要放一個輸入框,留下較大的區域能夠方便它點中以獲取焦點輸入。
borderWidth問題
這樣作使用borderWidth:0.5,這種寫法在ios上是能夠正常顯示,可是在部分Android機型上顯示異常。這個問題可使用 StyleSheet.hairlineWidth 來避免這個問題。
這裏分割線使用了行元素的下邊框來作,其實也能夠吧分割線做爲一個單獨的子元素來繪製,好比:
<View style={{height:1,backgroundColor:'#dddddd'}}></View>
分割線問題
跟效果圖對比行元素的分割線沒有撐滿,而是隨行內容同樣存在內襯。這個問題,若是採用上面的方法把分割線做爲子元素,則能夠解決。
若是使用邊框的話,能夠在行元素內再包一層View,外層View設置padding,內層view設置borderBottomWidth便可。
最終代碼:
class Layout extends Component { render() { return ( <View style={{flex:1,backgroundColor:'#dddddd',flexDirection:'column',justifyContent:'center'}}> <View style={LayoutStyles.row}> <View style={LayoutStyles.rowContainer}> <Text>真實姓名</Text> <View style={{flex:1,alignItems:'flex-end',height:47}}> <TextInput style={LayoutStyles.inputTextName} underlineColorAndroid={'blue'} keyboardType={'default'} placeholder='請輸入' placeholderTextColor='#999999' defaultValue={'laochan'} maxLength={10} /> </View> </View> </View> <View style={LayoutStyles.row}> <View style={LayoutStyles.rowContainer}> <Text style={{flex:1}}>手機號碼</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>13812345678</Text> </View> </View> </View> </View> ); } } const LayoutStyles = StyleSheet.create({ row: { backgroundColor:'#ffffff', height:47, paddingHorizontal: 15 }, rowContainer: { flex: 1, flexDirection:'row', alignItems:'center', borderBottomWidth:StyleSheet.hairlineWidth, borderBottomColor:'#dddddd', }, inputTextName: { flex:1, padding:0, fontSize:14, color: '#999999', textAlign: 'right', marginRight: 10 } });
參考資源:
http://reactnative.cn/docs/0.44/layout-with-flexbox.html#content
佈局樣式屬性:http://reactnative.cn/docs/0.44/layout-props.html
flex佈局:http://www.ruanyifeng.com/blog/2015/07/flex-examples.html