React Native之FlexBox介紹和使用

来源:http://www.cnblogs.com/miaomiaoshen/archive/2016/10/28/6006971.html
-Advertisement-
Play Games

前言 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 "HTML快速入門(一)" 學習 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝 文章第一版出自簡書,如果 ...


# 前言

  • 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 HTML快速入門(一) 學習

  • 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝

  • 文章第一版出自簡書,如果出現圖片或頁面顯示問題,煩請轉至 簡書 查看 也希望喜歡的朋友可以點贊,謝謝

什麼是 FlexBox 佈局


  • 在 html 中,界面的搭建都是採用 CSS 的佈局方式,CSS 是基於盒子模型,依賴於 display、position、float屬性,這對於一些比如 垂直居中 的特殊佈局來說非常不方便

  • Flex 是一種全新的針對 Web 和移動開發的佈局方式,它可以簡便、完整、響應式地實現各種頁面佈局,並且目前的所有瀏覽器已經支持這種佈局方式,所以不用考慮相容性方面的問題

  • FlexBox 從字面上可以理解成:能夠很容易變化以適應外界條件變化的通用矩形容器,也就是我們常聽到的 彈性佈局,它的宗旨就是 通過彈性的方式來第七和分佈容器中內容的空間,使其能使用不同屏幕,為盒裝模型提供最大的靈活性(這類似於 iOS 開發中的AtuoLayout佈局方式)

  • FlexBox 佈局主要思想是:讓容器有能力讓其子項目改變寬度、高度甚至是順序,從而達到最佳填充可用空間的方式

  • React Native 中的 FlexBox 是這個規範的一個子集

  • 綜上所述,FlexBox 就是用來解決 父盒子 和 子盒子 之間的約束關係,如下圖

父盒子和子盒子之間的約束關係

  • FlexBox 在開發中能夠解決下麵等問題
    • 浮動佈局
    • 水平和垂直居中
    • 自動分配寬度
    • 各種機型屏幕適配
    • 動態分配子集的尺寸、位置等等
  • 如下圖所示,在 CSS 中,常規的佈局是基於塊和內聯流方向,而 Flex佈局是基於 Flexflow流【容器預設存在兩根軸:水平的主軸(main axis)垂直的交叉軸(cross axis),主軸的開始位置(與邊框的交叉點)叫做 main start,結束的位置叫 main end;交叉軸的開始位置叫做 cross start,結束位置叫做 cross end。項目預設沿著主軸排列,單個項目占據的主軸空間叫做 main size,占據的交叉軸空間叫做 cross size】

FlexBox主軸與側軸的關係

  • 根據伸縮項目排列方式的不同,主軸和側軸方向也會變化,如下圖所示

主軸從左向右排列

主軸從上向下排列

獲取主屏幕尺寸

  • 為了後面更好的展示案例,我們先來看看如何獲取主屏幕的尺寸和解析度
    • 首先,我們需要先導入 Dimensions


        // 導入類庫
        var Dimensions = require('Dimensions');
    
    • 接下來就可以在需要的地方使用 Dimensions 變數獲取屏幕的高度、寬度、解析度等等數據
        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
            },
        });
    

    效果:
    使View尺寸等於屏幕尺寸

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'
        },
    

    效果:
    主軸垂直,起點在下邊

  • 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'
        },
    

    效果:
    伸縮項目會平均分佈在行內,兩端保留一半的空間

  • 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'
        },
    

    效果:
    如果項目沒有設置高度或設置為 auto,將占滿整個容器高度

  • 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'
        },
    

    效果:
    換行,第一行在上方

FlexBox 常用元素屬性


  • flex(flex-grow、flex-shrink、flex-basis三個屬性的縮寫,第二個參數和第三個參數是可選參數):預設值為 "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'
            },
        });
    

    效果:
    初始化視圖

    • 現在我們給紅色項目設置 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>
    

    效果:
    示例二

    • 現在我們再設置黃色項目的 flex 為2,可以看出,紅色和綠色所占的空間和等同於黃色項目,並且紅色和綠色平分了除黃色項目以外的空間,現在我們應該能理解上面公式的意思了吧(項目寬度 = 父項目的寬度 * (子項目自身比例 / 所有父項目內子項目的比例))


        <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>
    

    效果:
    示例三

    • 但是不知道各位發現了沒有,雖然我們每個子項目都同時設置了高度和寬度,但是卻只有寬度改變,而高度則一直保持我們設置的狀態,是不是 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 會遵循我們所設置的高度,不去進行拉伸,反之將會對高度進行拉伸
    • 根據 flex 的特性,如果沒有設置 View 的尺寸情況下,使用 flex 也可以讓 View 占滿整個屏幕


        container: {
            backgroundColor:'blue',
            flex:1
        },
    
  • alignSelf(允許單個項目有與其它項目不一樣的對齊方式,可覆蓋 align-items屬性)
    • auto(預設):繼承父元素的alignItems屬性,如果沒有則切換為stretch


        subViewStyle2: {
            backgroundColor:'yellow',
            height:60,
            width:60,
            alignSelf:'auto'
        },
    

    效果:
    繼承父元素的alignItems屬性,如果沒有則切換為stretch

    • 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'
        },
    

    效果:
    Snip20161027_22.png

我們 FlexBox 的使用就先簡單介紹到這裡,在後續的文章中,會在實際的開發場景中帶大家更多更細緻地講解 FlexBox,如果你覺得哪裡寫得不好或者有誤,麻煩留言或者用郵箱的方式聯繫我,當然遇到問題也可以,最後如果喜歡我的文章,還請點個贊並關註,讀者的肯定是對我們筆者最大的鼓勵,謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Android Studio常用快捷鍵 Android Studio日常開發常用快捷鍵. 快捷鍵版本: Mac OS X 10.5+ 搜索查看類 | 用途 | Mac快捷鍵 | |: |: | | 搜索所有文件 | double Shift | | 搜索文件 | Cmd + Shift + O | ...
  • 實現的效果比較簡單類似於微信打開網頁,頭部有個進度條顯示載入進度 下載地址:http://download.csdn.net/detail/qq_29774291/9666941 1.在安卓端載入一個網頁 2.顯示網頁開始載入和載入的進度;不過在有時會出現onPageStarted等多次調用的情況, ...
  • 前幾天將我的Xcode升到了8,但是在運行程式時,會列印很多沒有用的信息,如下圖: Xcode8運行程式時列印的亂碼 Xcode8運行程式時列印的亂碼 於是各種尋求答案,找到如下答案: Edit Scheme-> Run -> Arguments, 在Environment Variables裡邊添 ...
  • 本文是轉載的,轉載地址: "大白話解釋Strategy模式和State模式的區別" 先上圖: 本質上講,策略模式和狀態模式做得是同一件事:去耦合。怎麼去耦合?就是把乾什麼(語境類)和怎麼乾(策略介面)分開,互不依賴。打個比方,下麵是我一天的行程: 但問題來了,啪啪啪是個技術活,有著名的48式,今天到 ...
  • 如今,隨著信息技術的不斷發展,很多公司採用微信企業號來進行企業與員工之間的聯繫。其實微信企業號中右很多獨立的應用。 那麼如何可以將報表系統集成到微信中呢?這裡分享一下在微信企業號中創建獨立的報表應用,並且將微信賬號單點登錄到帆軟報表軟體FineReport的許可權對接。 ...
  • 現在大部分應用程式都把業務邏輯處理,數據調用等功能封裝成了服務的形式,應用程式只需要調用這些web服務就好了,在這裡就不贅述web服務的優點了。本文總結如何在android中調用Web服務,通過傳遞基類型和複雜類型對比調用.NET平臺發佈的WCF服務和WebService服務之間的區別。 0 寫在前 ...
  • 前言 學習ios這幾天來,總結下,函數的定義,調用。跟其他語言都有一定的區別; 幾個特別重要的就是對象的迭代的使用和判斷、取隨機數、動畫的實現及數組的深入研究等等 之前的總結地址 ios開發 學習積累20161024~20161026: http://www.cnblogs.com/jasonxu1 ...
  • 鏈接 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...