React Native flexBox佈局(一)

ZY_FlyWay發表於2017-08-03

序:

    佈局想必大家都知道,在iOS 中我們使用程式碼計算螢幕寬高佈局,使用Autoresizing和AutoLayout進行佈局。在web中的佈局一般都是依靠CSS的盒子模型,09年W3C提出了一種新的佈局方案,Flex佈局。ReactNative就是選用了這種佈局方式。下面我們來看下FlexBox佈局吧。


1、FlexBox是什麼

Flex 是Flexible Box的縮寫,字面上的意思就是彈性盒子。意為“彈性佈局”用來為盒狀模型提供最大的靈活性。

  • flexible(形容詞):能夠伸縮或者很容易變化,以適應外界條件的變化
  • box(名詞):通用的矩形容器
FlexBox佈局的理解:

   跟iOS AutoLayout比,我認為FlexBox的主要特點就是容器的子集可以根據容器的大小按比分配,還有豐富的對齊方式。


2、FlexBox基本概念

採用 Flex 佈局的元素,稱為 Flex 容器(flex container),簡稱"容器"。它的所有子元素自動成為容器成員,稱為 Flex 專案(flex item),簡稱"專案"。

容器預設存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end

專案預設沿主軸排列。單個專案佔據的主軸空間叫做main size,佔據的交叉軸空間叫做cross size



3、容器的屬性

以下4個屬性設定在容器上,阮一峰老師介紹的進行了篩檢,只寫現在可用的幾個
  • flexDirection
  • flexWrap
  • justifyContent
  • alignItems

3.1 flexDirection屬性

    

    flexDirection屬性決定主軸的方向(即專案的排列方向)。

    主要四個屬性值:

  • row    主軸方向為橫向,從左到
  • row-reverse   橫向,反方向
  • column            豎向,自上向下
  • column-reverse  豎向,自下向上
    下面有一段demo,分別設定四個屬性看下結果:
    
程式碼如下:
     
import React, { Component } from 'react';
import {
   AppRegistry,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
} from 'react-native';


class RNHybrid extends Component {

  render() {
    return(
        <View> //切換flexDirection屬性看結果
        <View style={{backgroundColor:'red',width:100,height:40,marginTop:100}}>
        </View>
        <View style={{backgroundColor:'yellow',width:100,height:40,marginTop:100}}>
        </View>
        <View style={{backgroundColor:'blue',width:100,height:40,marginTop:100}}>
        </View>
        </View>
      );
  }
}

AppRegistry.registerComponent('RNHybrid', () => RNHybrid);


1.預設是column效果如下:



2. column   最外層View的屬性加上style={{flexDirection:'column-reverse'}}  翻轉了效果如下:



下面屬性的就不貼了,自己試試就知道了。



3.2 flexWrap屬性


如果我們的主軸為橫向正向,那麼我們的子控制元件排不開了怎麼辦?會自動換行嗎?

程式碼是把上面的View寬度都變成三個加一塊能超過螢幕的寬度,我的模擬器是6s,我讓三個子View寬度為150。

觀察demo看下答案:



預設flexWrap屬性是不換行,下面來學習下這個屬性。

flexWrap: nowrap | wrap | wrap-reverse


wrap換行效果:





3.3 justifyContent屬性

justifyContent屬性定義了專案在主軸上的對齊方式。(自己試驗是在橫軸上)


  justifyContent: flex-start | flex-end | center | space-between | space-around;

它可能取5個值,具體對齊方式與軸的方向有關。下面假設主軸為從左到右。

  • flex-start(預設值):左對齊
  • flex-end:右對齊
  • center: 居中
  • space-between:兩端對齊,專案之間的間隔都相等。
  • space-around:每個專案兩側的間隔相等。所以,專案之間的間隔比專案與邊框的間隔大一倍。

3.4 alignItems屬性

alignItems屬性定義專案在交叉軸上如何對齊。

  alignItems: flex-start | flex-end | center | baseline | stretch;

它可能取5個值。具體的對齊方式與交叉軸的方向有關,下面假設交叉軸從上到下。

  • flex-start:交叉軸的起點對齊。
  • flex-end:交叉軸的終點對齊。
  • center:交叉軸的中點對齊。
  • baseline: 專案的第一行文字的基線對齊。
  • stretch(預設值):如果專案未設定高度或設為auto,將佔滿整個容器的高度。

4、元素的屬性

  • alignSelf
  • flexGrow
  • flexShrink
  • flexBasis
  • flex

4.1 alignSelf屬性

 
 alignSelf屬性允許單個專案有與其他專案不一樣的對齊方式,可覆蓋alignItems屬性。預設值為auto,表示繼承父元素的alignItems屬性,如果沒有父元素,則等同於stretch

alignSelf: auto | flex-start | flex-end | center | baseline | stretch;


應用demo:

import React, { Component } from 'react';
import {
   AppRegistry,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
} from 'react-native';


class RNHybrid extends Component {

  render() {
    return(
        <View style={{flexDirection:'row',justifyContent:'space-around',alignItems:'flex-start'}}>
        <View style={{backgroundColor:'red',width:30,height:30,marginTop:100,alignSelf:'flex-end'}}>
        </View>
        <View style={{backgroundColor:'yellow',width:30,height:40,marginTop:100}}>
        </View>
        <View style={{backgroundColor:'blue',width:30,height:50,marginTop:100}}>
        </View>
        </View>
      );
  }
}

AppRegistry.registerComponent('RNHybrid', () => RNHybrid);

效果:


其他效果可以修改屬性嘗試。

4.2 flexGrow屬性



flex-grow屬性定義專案的放大比例,預設為0,即如果存在剩餘空間,也不放大。


 程式碼:

 

render() {
    return(
        <View style={{flexDirection:'row',justifyContent:'space-around',alignItems:'flex-start'}}>
        <View style={{backgroundColor:'red',width:30,height:30,marginTop:100,flexGrow:1}}>
        </View>
        <View style={{backgroundColor:'yellow',width:30,height:40,marginTop:100,flexGrow:2}}>
        </View>
        <View style={{backgroundColor:'blue',width:30,height:50,marginTop:100,flexGrow:1}}>
        </View>
        </View>
      );
  }


效果:





總結:我們可以看出,這個屬性不受原來寬度的限制,從新按比例分配。

注意:如果第一個紅色View控制元件該屬性為0或者沒有該屬性,其他兩個View擁有該屬性,那麼這個View會把這行紅色View所佔空間剩下的空間按比例分配。如Demo2


Demo2:

程式碼:

return(
        <View style={{flexDirection:'row',justifyContent:'space-around',alignItems:'flex-start'}}>
        <View style={{backgroundColor:'red',width:250,height:30,marginTop:100}}>
        </View>
        <View style={{backgroundColor:'yellow',width:30,height:40,marginTop:100,flexGrow:2}}>
        </View>
        <View style={{backgroundColor:'blue',width:30,height:50,marginTop:100,flexGrow:1}}>
        </View>
        </View>
      );

效果:


4.3 flexShrink屬性


        flexShrink屬性定義了專案的縮小比例,預設為1,即如果空間不足,該專案將縮小。

程式碼:

return(
        <View style={{flexDirection:'row',justifyContent:'space-around',alignItems:'flex-start'}}>
        <View style={{backgroundColor:'red',width:100,height:30,marginTop:100,flexShrink:0}}>
        </View>
        <View style={{backgroundColor:'yellow',width:200,height:40,marginTop:100,flexShrink:1}}>
        </View>
        <View style={{backgroundColor:'blue',width:200,height:50,marginTop:100,flexShrink:0}}>
        </View>
        </View>
      );


效果:





總結:不難看出,flexShrink屬性值是1的時候程式碼,空間不足的時候縮放,flexShrink 0的時候不縮放。


4.4 flexBasis屬性


  flexBasis屬性定義了在分配多餘空間之前,專案佔據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多餘空間。它的預設值為auto,即專案的本來大小。


程式碼:

render() {
    return(
        <View style={{flexDirection:'row',alignItems:'flex-end'}}>
        <View style={{backgroundColor:'red',width:200,height:30,marginTop:100,flexShrink:1}}>
        </View>
        <View style={{backgroundColor:'yellow',width:200,height:40,marginTop:100,flexBasis:350}}>
        </View>
        <View style={{backgroundColor:'blue',width:200,height:50,marginTop:100,flexShrink:1}}>
        </View>
        </View>
      );
  }

效果:




4.5 flex屬性


  flex屬性,我認為對於彈性佈局是一個很重要的屬性,以後應用較多。
  flex屬性是flex-growflex-shrink 和 flex-basis的簡寫,預設值為0 1 auto。後兩個屬性可選。

程式碼:

render() {
    return(
        <View style={{flexDirection:'row',alignItems:'flex-end'}}>
        <View style={{backgroundColor:'red',width:200,height:30,marginTop:100,flex:1}}>
        </View>
        <View style={{backgroundColor:'yellow',width:200,height:40,marginTop:100,flex:2}}>
        </View>
        <View style={{backgroundColor:'blue',width:200,height:50,marginTop:100,flex:3}}>
        </View>
        </View>
      );
  }

效果:




總結:
     寬度 = 彈性寬度 * ( flexGrow / sum( flexGorw ) )

     建議優先使用這個屬性,而不是單獨寫三個分離的屬性,因為瀏覽器會推算相關值。

參考博文:

相關文章