本文只是簡(jiǎn)單地介紹下在React-Native中,使用CSS的Flex布局方式,完成RN中的控件布局,掌握這個(gè)布局方式對(duì)于后續(xù)開(kāi)發(fā)有非常大的用途。
什么是Flexbox
Flexbox(Flexible Box)旨在提供一個(gè)更加有效的方式制定、調(diào)整和分布一個(gè)容器里的項(xiàng)目布局,即使他們的大小是未知或者是動(dòng)態(tài)的。Flex布局主要思想是讓容器有能力讓其子項(xiàng)目能夠改變其寬度、高度(甚至順序),以最佳方式填充可用空間(主要是為了適應(yīng)所有類型的顯示設(shè)備和屏幕大?。?。Flex容器會(huì)使子項(xiàng)目(伸縮項(xiàng)目)擴(kuò)展來(lái)填滿可用空間,或縮小他們以防止溢出容器。
與CSS的主要差異
React Native中的Flexbox的工作原理和web上的CSS基本一致,當(dāng)然也存在少許差異。首先是默認(rèn)值不同:
flexDirection
的默認(rèn)值是column
而不是row
,alignItems
的默認(rèn)值是stretch
而不是flex-start
,以及flex
只能指定一個(gè)數(shù)字值。
基本要素
因?yàn)镕lexbox是整個(gè)模塊,不是一個(gè)屬性,它涉及很多東西,包括其整個(gè)組屬性。他們當(dāng)中一部分是容器(父元素,稱為“伸縮容器”),另一部分是子元素(稱為“伸縮項(xiàng)目”)。常規(guī)布局是基于塊和內(nèi)聯(lián)流方向,而Flex布局是基于flex-flow流。請(qǐng)看看來(lái)自w3c規(guī)范中的這張圖,解釋了flex布局的主要思想。
屬性
- 父容器的屬性
- flexDirection: row | row-reverse | column(默認(rèn)) | column-reverse 表明容器里面的子元素的排列方向。
- flexWrap: nowrap(默認(rèn)) | wrap | wrap-reverse 如果子元素溢出父容器的時(shí)候是否進(jìn)行換行。
- justifyContent: flex-start | flex-end | center | space-between | space-around; 這一個(gè)容器子元素橫向排版在容器的哪個(gè)位置
- alignItems: flex-start | flex-end | center | baseline | stretch; 這個(gè)容器子元素縱向排版在容器的哪個(gè)位置
- 子容器的屬性
- alignSelf: auto | flex-start | flex-end | center | stretch; 特定某個(gè)子元素的排布情況;
- position: relative(默認(rèn))| absolute;相比較Android由父視圖決定布局的規(guī)則來(lái)說(shuō),React-Native是由子視圖決定布局方式的
例子
-
flexDirection
:
export default class LearnFlexBox extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.sub} backgroundColor='#333333'/>
<View style={styles.sub} backgroundColor='#FF0000'/>
<View style={styles.sub} backgroundColor='#00FF00'/>
<View style={styles.sub} backgroundColor='#0000FF'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column', // row
height: 400,
},
sub: {
flex: 1,
height: 50,
}
});
-
alignItems
:
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
height: 400,
alignItems: 'stretch', // flex-start, flex-end, center, stretch, 當(dāng)設(shè)置為stretch時(shí),子容器的height屬性不能設(shè)置
},
sub: {
flex: 1,
// height: 50,
}
});
-
justifyContent
,有垂直就有水平:
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
height: 400,
justifyContent: 'flex-start', // flex-start, flex-end, center, space-between, space-around
},
sub: {
height: 300,
width: 50,
}
});
-
alignSelf
:
export default class LearnFlexBox extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.sub1} backgroundColor='#333333'/>
<View style={styles.sub2} backgroundColor='#FF0000'/>
<View style={styles.sub3} backgroundColor='#00FF00'/>
<View style={styles.sub4} backgroundColor='#0000FF'/>
<View style={styles.sub5} backgroundColor='#ABCDEF'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
height: 600,
},
sub1: {
flex: 1,
alignSelf: 'stretch', // auto, flex-start, flex-end, center, stretch
},
sub2: {
flex: 1,
height: 300,
alignSelf: 'flex-start',
},
sub3: {
flex: 1,
height: 300,
alignSelf: 'flex-end',
},
sub4: {
flex: 1,
height: 300,
alignSelf: 'center',
},
sub5: {
flex: 1,
height: 300,
alignSelf: 'auto',
}
});
-
flex
,主要控制子容器在父容器中的占比,如圖:
sub1: {
flex: 1,
alignSelf: 'stretch', // auto, flex-start, flex-end, center, stretch
},
sub2: {
flex: 2,
height: 300,
alignSelf: 'flex-start',
},
sub3: {
flex: 3,
height: 300,
alignSelf: 'flex-end',
},
sub4: {
flex: 4,
height: 300,
alignSelf: 'center',
},
sub5: {
flex: 5,
height: 300,
alignSelf: 'auto',
}
-
position
,主要控制子視圖的布局方式,如圖: -
relative
布局:
sub6: {
position: 'relative',
height: 100,
width: 100
}
```
sub6: {
position: 'relative',
left: 10,
height: 100,
width: 100
},
```
注:以上兩種`relative`的不同之處在于后者比前者多了一句`left: 10`這個(gè)布局,導(dǎo)致了`sub6`的涂層位置直接跟`sub1`黑色的圖層處于同一層級(jí)了,并不像前者那樣是在整個(gè)圖層的最外層,因此我們得出的結(jié)論是:
當(dāng)postion鍵的值為`relative`時(shí),不可以使用`bottom`和`right`鍵繼續(xù)描述位置,`top`和`left`鍵表示當(dāng)前組件距離上一個(gè)同級(jí)組件最上(左)沿有多少pt
-
absolute
布局:
sub7: {
position: 'absolute',
left: -90,
height: 100,
width: 100
}
```
sub7: {
position: 'absolute',
left: 10,
height: 100,
width: 100
}
```
```
sub7: {
position: 'absolute',
left: 80,
height: 100,
width: 100
}
```
```
sub7: {
position: 'absolute',
left: 200,
height: 100,
width: 100
}
```
注:以上四種`absolute`的不同之處在于`left: xxx`這個(gè)布局的值不一樣,導(dǎo)致了`sub7`的涂層位置在不斷變化,仔細(xì)觀察我們得出的結(jié)論是:
使用`absolute`布局子視圖時(shí),子視圖所處的圖層 = 該子視圖是否有“接觸”的父視圖的層級(jí) + 1
參考資料
一個(gè)完整的Flexbox指南
3分鐘輕松玩轉(zhuǎn)React Native中position、flexbox布局
A Complete Guide to Flexbox
React Native 之 flexbox 布局詳解篇
React-Native中文網(wǎng)