前言
學習本系列內容需要具備一定 HTML 開發(fā)基礎畅铭,沒有基礎的朋友可以先轉至 HTML快速入門(一) 學習
本人接觸 React Native 時間并不是特別長,所以對其中的內容和性質了解可能會有所偏差,在學習中如果有錯會及時修改內容府框,也歡迎萬能的朋友們批評指出催跪,謝謝
文章第一版出自簡書,如果出現(xiàn)圖片或頁面顯示問題惑艇,煩請轉至 簡書 查看 也希望喜歡的朋友可以點贊蒿辙,謝謝
什么是 FlexBox 布局
在 html 中,界面的搭建都是采用 CSS 的布局方式滨巴,CSS 是基于
盒子模型
思灌,依賴于 display、position恭取、float屬性泰偿,這對于一些比如垂直居中
的特殊布局來說非常不方便Flex 是一種全新的針對 Web 和移動開發(fā)的布局方式,它可以簡便蜈垮、完整耗跛、響應式地實現(xiàn)各種頁面布局,并且目前的所有瀏覽器已經(jīng)支持這種布局方式攒发,所以不用考慮兼容性方面的問題
FlexBox 從字面上可以理解成:能夠很容易變化以適應外界條件變化的通用矩形容器调塌,也就是我們常聽到的
彈性布局
,它的宗旨就是通過彈性的方式來第七和分布容器中內容的空間惠猿,使其能使用不同屏幕羔砾,為盒裝模型提供最大的靈活性
(這類似于 iOS 開發(fā)中的AtuoLayout布局方式)FlexBox 布局主要思想是:讓容器有能力讓其子項目改變寬度、高度甚至是順序偶妖,從而達到最佳填充可用空間的方式
React Native 中的 FlexBox 是這個規(guī)范的一個子集
綜上所述姜凄,F(xiàn)lexBox 就是用來解決 父盒子 和 子盒子 之間的約束關系,如下圖
-
FlexBox 在開發(fā)中能夠解決下面等問題
- 浮動布局
- 水平和垂直居中
- 自動分配寬度
- 各種機型屏幕適配
- 動態(tài)分配子集的尺寸餐屎、位置等等
如下圖所示檀葛,在 CSS 中,常規(guī)的布局是基于塊和內聯(lián)流方向腹缩,而 Flex布局是基于
Flexflow流
【容器默認存在兩根軸:水平的主軸(main axis)
和垂直的交叉軸(cross axis)
屿聋,主軸的開始位置(與邊框的交叉點)叫做 main start,結束的位置叫 main end;交叉軸的開始位置叫做 cross start,結束位置叫做 cross end空扎。項目默認沿著主軸排列,單個項目占據(jù)的主軸空間叫做 main size,占據(jù)的交叉軸空間叫做 cross size】
- 根據(jù)伸縮項目排列方式的不同润讥,主軸和側軸方向也會變化转锈,如下圖所示
獲取主屏幕尺寸
-
為了后面更好的展示案例,我們先來看看如何獲取主屏幕的尺寸和分辨率
- 首先楚殿,我們需要先導入
Dimensions
庫
// 導入類庫 var Dimensions = require('Dimensions');
- 接下來就可以在需要的地方使用
Dimensions
變量獲取屏幕的高度撮慨、寬度、分辨率等等數(shù)據(jù)
export default class TestRN extends Component { render() { return ( <View style={styles.container}> <Text>當前屏幕的寬度:{Dimensions.get('window').width}</Text> <Text>當前屏幕的高度:{Dimensions.get('window').height}</Text> </View> ); } }
- 設置樣式
// 樣式 const styles = StyleSheet.create({ container: { backgroundColor:'blue' }, });
- 首先楚殿,我們需要先導入
-
既然能拿到屏幕的尺寸脆粥,那么就能夠直接將主 View 的大小設置成屏幕的尺寸砌溺,使 View 填充整個屏幕
// 樣式 const styles = StyleSheet.create({ container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width }, });
效果:
FlexBox 常用容器屬性
-
為了方便理解,我們先添加幾個視圖
// 導入類庫 var Dimensions = require('Dimensions'); // 入口 export default class TestRN extends Component { render() { return ( <View style={styles.container}> <View style={styles.subViewStyle1}></View> <View style={styles.subViewStyle2}></View> <View style={styles.subViewStyle3}></View> </View> ); } } // 樣式 const styles = StyleSheet.create({ container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width }, subViewStyle1: { backgroundColor:'red', height:60, width:60, }, subViewStyle2: { backgroundColor:'yellow', height:60, width:60, }, subViewStyle3: { backgroundColor:'green', height:60, width:60, }, });
效果:
-
flexDirection(該屬性決定了項目排列的方向变隔,也就是主軸的方向)
- row:主軸為水平方向规伐,起點在左端
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'row' },
效果:
-
row-reverse:主軸為水平方向,起點在右端
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'row-reverse' },
效果:
-
column(默認):主軸為垂直方向猖闪,起點在上
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'column' },
效果:
-
column-reverse:主軸為垂直方向肌厨,起點在下
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'column-reverse' },
效果:
- row:主軸為水平方向规伐,起點在左端
-
justifyContent(定義伸縮項目在主軸線的對齊方式)
- flex-start(默認):伸縮項目向一行的起始位置靠齊
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置子項目在主軸上的對齊方式 justifyContent:'flex-start' },
效果:
- flex-end:伸縮項目向一行的結束位置靠齊
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置子項目在主軸上的對齊方式 justifyContent:'flex-end' },
效果:
- center:伸縮項目向一行的中間位置靠齊
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置子項目在主軸上的對齊方式 justifyContent:'center' },
效果:
- space-between:兩端對齊,項目之間的間隔都相等
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置子項目在主軸上的對齊方式 justifyContent:'space-between' },
效果:
- space-around:伸縮項目會平均分布在行內吵护,兩端保留一半的空間
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置子項目在主軸上的對齊方式 justifyContent:'space-around' },
效果:
- flex-start(默認):伸縮項目向一行的起始位置靠齊
-
alignItems(定義項目在交叉軸上如何對齊胁镐,可以把它看成側軸(垂直于主軸)的對齊方式)
- flex-start(默認):側軸軸的起點對齊
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置項目在側軸上如何對齊 alignItems:'flex-start' },
效果:
- flex-end:
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置項目在側軸上如何對齊 alignItems:'flex-end' },
效果:
- center:側軸的中點對齊
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置項目在側軸上如何對齊 alignItems:'center' },
效果:
- stretch(默認):如果項目沒有設置高度或設置為 auto,將占滿整個容器高度
container: { backgroundColor:'blue', 注釋掉高度 // height:Dimensions.get('window').height, // width:Dimensions.get('window').width, // 設置項目在側軸上如何對齊 alignItems:'stretch' },
效果:
- flex-start(默認):側軸軸的起點對齊
-
flexWrap(默認情況下哼审,項目都排在一條軸線上,flex-wrap屬性定義如果一條軸線排不下,如何換行)
- nowrap(默認):不換行
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'row', // 設置換行的方式 flexWrap:'nowrap' },
效果:
- wrap:換行离福,第一行在上方
container: { backgroundColor:'blue', height:Dimensions.get('window').height, width:Dimensions.get('window').width, // 設置主軸方向 flexDirection:'row', // 設置換行的方式 flexWrap:'wrap' },
效果:
- nowrap(默認):不換行
FlexBox 常用元素屬性
-
flex(flex-grow、flex-shrink、flex-basis三個屬性的縮寫,
第二個參數(shù)和第三個參數(shù)是可選參數(shù)
):默認值為 "0 1 auto"- 寬度 = 彈性寬度 * (flexGrow / sum(flexGorw))(重要)
- 先來做一下實驗,看看flex到底是干嘛的徘郭,首先捆毫,我們先初始化一個新視圖江醇,便于理解
// 入口 export default class TestRN extends Component { render() { return ( <View style={styles.container}> <View style={{backgroundColor:'red', height:60, width:60}}></View> <View style={{backgroundColor:'green', height:60, width:60}}></View> <View style={{backgroundColor:'yellow', height:60, width:60}}></View> </View> ); } } // 樣式 const styles = StyleSheet.create({ container: { backgroundColor:'blue', flex:1, // 設置主軸方向為水平,起點在左 flexDirection:'row' }, });
效果:
- 現(xiàn)在我們給紅色項目設置 flex 為1条辟,可以看到紅色項目的寬度填充了除去 綠色項目和黃色項目 的部分
<View style={{backgroundColor:'red', height:60, width:60, flex:1}}></View>
效果:
- 接著再給綠色項目也設置 flex 為1杭棵,可以看到紅色項目和綠色項目填充了 除黃色項目 的部分,并且紅色和綠色項目各占剩下空間的一半
<View style={{backgroundColor:'red', height:60, width:60, flex:1}}></View> <View style={{backgroundColor:'green', height:60, width:60, flex:1}}></View>
效果:
- 現(xiàn)在我們再設置黃色項目的 flex 為2,可以看出耘擂,紅色和綠色所占的空間和等同于黃色項目,并且紅色和綠色平分了除黃色項目以外的空間,現(xiàn)在我們應該能理解上面公式的意思了吧(項目寬度 = 父項目的寬度 * (子項目自身比例 / 所有父項目內子項目的比例))
<View style={{backgroundColor:'red', height:60, width:60, flex:1}}></View> <View style={{backgroundColor:'green', height:60, width:60, flex:1}}></View> <View style={{backgroundColor:'yellow', height:60, width:60, flex:3}}></View>
效果:
- 但是不知道各位發(fā)現(xiàn)了沒有秩霍,雖然我們每個子項目都同時設置了高度和寬度篙悯,但是卻只有寬度改變,而高度則一直保持我們設置的狀態(tài)铃绒,是不是
flex屬性
只對寬度有效呢鸽照?接下來我們來修改下代碼,看看是不是真的如我們想象的這樣 ———— 這里我們將綠色的高度去掉颠悬,可以看出矮燎,綠色項目的高度填充了整個父項目的高度
<View style={{backgroundColor:'red', height:60, width:60, flex:1}}></View> <View style={{backgroundColor:'green', width:60, flex:1}}></View> <View style={{backgroundColor:'yellow', height:60, width:60, flex:3}}></View>
效果:
- 總結以上的示例,可以看出赔癌,不管是否設置子項目的寬度诞外,flex都會忽略寬度,按照上面的
公式
進行縮放灾票,如果我們設置了高度峡谊,那么 flex 會遵循我們所設置的高度,不去進行拉伸刊苍,反之將會對高度進行拉伸
- 根據(jù) flex 的特性既们,如果沒有設置 View 的尺寸情況下,使用 flex 也可以讓 View 占滿整個屏幕
container: { backgroundColor:'blue', flex:1 },
-
alignSelf(允許單個項目有與其它項目不一樣的對齊方式正什,可覆蓋 align-items屬性)
- auto(默認):繼承父元素的alignItems屬性啥纸,如果沒有則切換為stretch
subViewStyle2: { backgroundColor:'yellow', height:60, width:60, alignSelf:'auto' },
效果:
- flex-start:項目從側軸的起點開始
subViewStyle2: { backgroundColor:'yellow', height:60, width:60, alignSelf:'flex-start' },
效果:
- flex-end:項目從側軸的終點開始
subViewStyle2: { backgroundColor:'yellow', height:60, width:60, alignSelf:'flex-end' },
效果:
- center:項目以側軸的中心為參照
subViewStyle2: { backgroundColor:'yellow', height:60, width:60, alignSelf:'center' },
效果:
- stretch
subViewStyle2: { backgroundColor:'yellow', height:60, width:60, alignSelf:'stretch' },
效果:
- auto(默認):繼承父元素的alignItems屬性啥纸,如果沒有則切換為stretch