<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                在前面兩篇文章中,我們一起學習了構建視圖的基本元素:文本、圖片和按鈕,用于展示一組連續視圖元素的 ListView,以及處理多重嵌套的可滾動視圖的 CustomScrollView。 在 Flutter 中,一個完整的界面通常就是由這些小型、單用途的基本控件元素依據特定的布局規則堆砌而成的。那么今天,我就帶你一起學習一下,在 Flutter 中,搭建出一個漂亮的布局,我們需要了解哪些布局規則,以及這些規則與其他平臺類似概念的差別在哪里。希望這樣的設計,可以幫助你站在已有經驗的基礎上去高效學習 Flutter 的布局規則。 我們已經知道,在 Flutter 中一切皆 Widget,那么布局也不例外。但與基本控件元素不同,布局類的 Widget 并不會直接呈現視覺內容,而是作為承載其他子 Widget 的容器。 這些布局類的 Widget,內部都會包含一個或多個子控件,并且都提供了擺放子控件的不同布局方式,可以實現子控件的對齊、嵌套、層疊和縮放等。而我們要做的就是,通過各種定制化的參數,將其內部的子 Widget 依照自己的布局規則放置在特定的位置上,最終形成一個漂亮的布局。 Flutter 提供了 31 種[布局 Widget](https://flutter.dev/docs/development/ui/widgets/layout),對布局控件的劃分非常詳細,一些相同(或相似)的視覺效果可以通過多種布局控件實現,因此布局類型相比原生 Android、iOS 平臺多了不少。比如,Android 布局一般就只有 FrameLayout、LinearLayout、RelativeLayout、GridLayout 和 TableLayout 這 5 種,而 iOS 的布局更少,只有 Frame 布局和自動布局兩種。 為了幫你建立起對布局類 Widget 的認知,了解基本布局類 Widget 的布局特點和用法,從而學以致用快速上手開發,在今天的這篇文章中,我特意挑選了幾類在開發 Flutter 應用時,最常用也最有代表性的布局 Widget,包括單子 Widget 布局、多子 Widget 布局、層疊 Widget 布局,與你展開介紹。 掌握了這些典型的 Widget,你也就基本掌握了構建一個界面精美的 App 所需要的全部布局方式了。接下來,我們就先從單子 Widget 布局聊起吧。 ## 單子 Widget 布局:Container、Padding 與 Center 單子 Widget 布局類容器比較簡單,一般用來對其唯一的子 Widget 進行樣式包裝,比如限制大小、添加背景色樣式、內間距、旋轉變換等。這一類布局 Widget,包括 Container、Padding 與 Center 三種。 Container,是一種允許在其內部添加其他控件的控件,也是 UI 框架中的一個常見概念。 在 Flutter 中,Container 本身可以單獨作為控件存在(比如單獨設置背景色、寬高),也可以作為其他控件的父級存在:Container 可以定義布局過程中子 Widget 如何擺放,以及如何展示。與其他框架不同的是,**Flutter 的 Container 僅能包含一個子 Widget**。 所以,對于多個子 Widget 的布局場景,我們通常會這樣處理:先用一個根 Widget 去包裝這些子 Widget,然后把這個根 Widget 放到 Container 中,再由 Container 設置它的對齊 alignment、邊距 padding 等基礎屬性和樣式屬性。 接下來,我通過一個示例,與你演示如何定義一個 Container。 在這個示例中,我將一段較長的文字,包裝在一個紅色背景、圓角邊框的、固定寬高的 Container 中,并分別設置了 Container 的外邊距(距離其父 Widget 的邊距)和內邊距(距離其子 Widget 的邊距): ~~~ Container( child: Text('Container(容器)在 UI 框架中是一個很常見的概念,Flutter 也不例外。'), padding: EdgeInsets.all(18.0), // 內邊距 margin: EdgeInsets.all(44.0), // 外邊距 width: 180.0, height:240, alignment: Alignment.center, // 子 Widget 居中對齊 decoration: BoxDecoration( //Container 樣式 color: Colors.red, // 背景色 borderRadius: BorderRadius.circular(10.0), // 圓角邊框 ), ) ~~~ :-: ![](https://img.kancloud.cn/fa/d7/fad72eb6917be0062df5a46a104f3ff7_828x1792.png) 圖 1 Container 示例 如果我們只需要將子 Widget 設定間距,則可以使用另一個單子容器控件 Padding 進行內容填充: ~~~ Padding( padding: EdgeInsets.all(44.0), child: Text('Container(容器)在 UI 框架中是一個很常見的概念,Flutter 也不例外。'), ); ~~~ :-: ![](https://img.kancloud.cn/24/a1/24a18be98054d93ddf8989aac1a5a5ae_828x1792.png) 圖 2 Padding 示例 在需要設置內容間距時,我們可以通過 EdgeInsets 的不同構造函數,分別制定四個方向的不同補白方式,如均使用同樣數值留白、只設置左留白或對稱方向留白等。如果你想更深入地了解這部分內容,可以參考這個[API 文檔](https://api.flutter.dev/flutter/painting/EdgeInsets-class.html#constructors)。 接下來,我們再來看看單子 Widget 布局容器中另一個常用的容器 Center。正如它的名字一樣,Center 會將其子 Widget 居中排列。 比如,我們可以把一個 Text 包在 Center 里,實現居中展示: ~~~ Scaffold( body: Center(child: Text("Hello")) // This trailing comma makes auto-formatting nicer for build methods. ); ~~~ :-: ![](https://img.kancloud.cn/c5/00/c500408d7df10249494a2a90cb815a65_1440x2560.png) 圖 3 Center 示例 需要注意的是,為了實現居中布局,Center 所占據的空間一定要比其子 Widget 要大才行,這也是顯而易見的:如果 Center 和其子 Widget 一樣大,自然就不需要居中,也沒空間居中了。因此 Center 通常會結合 Container 一起使用。 現在,我們結合 Container,一起看看 Center 的具體使用方法吧。 ~~~ Container( child: Center(child: Text('Container(容器)在 UI 框架中是一個很常見的概念,Flutter 也不例外。')), padding: EdgeInsets.all(18.0), // 內邊距 margin: EdgeInsets.all(44.0), // 外邊距 width: 180.0, height:240, decoration: BoxDecoration( //Container 樣式 color: Colors.red, // 背景色 borderRadius: BorderRadius.circular(10.0), // 圓角邊框 ), ); ~~~ 可以看到,我們通過 Center 容器實現了 Container 容器中**alignment: Alignment.center**的效果。 事實上,為了達到這一效果,Container 容器與 Center 容器底層都依賴了同一個容器 Align,通過它實現子 Widget 的對齊方式。Align 的使用也比較簡單,如果你想深入了解的話,可以參考[官方文檔](https://api.flutter.dev/flutter/widgets/Align-class.html),這里我就不再過多介紹了。 接下來,我們再看看多子 Widget 布局的三種方式,即 Row、Column 與 Expanded。 ## 多子 Widget 布局:Row、Column 與 Expanded 對于擁有多個子 Widget 的布局類容器而言,其布局行為無非就是兩種規則的抽象:水平方向上應該如何布局、垂直方向上應該如何布局。 如同 Android 的 LinearLayout、前端的 Flex 布局一樣,Flutter 中也有類似的概念,即將子 Widget 按行水平排列的 Row,按列垂直排列的 Column,以及負責分配這些子 Widget 在布局方向(行 / 列)中剩余空間的 Expanded。 Row 與 Column 的使用方法很簡單,我們只需要將各個子 Widget 按序加入到 chiildren 數組即可。在下面的代碼中,我們把 4 個分別設置了不同的顏色和寬高的 Container 加到 Row 與 Column 中: ~~~ //Row 的用法示范 Row( children: <Widget>[ Container(color: Colors.yellow, width: 60, height: 80,), Container(color: Colors.red, width: 100, height: 180,), Container(color: Colors.black, width: 60, height: 80,), Container(color: Colors.green, width: 60, height: 80,), ], ); //Column 的用法示范 Column( children: <Widget>[ Container(color: Colors.yellow, width: 60, height: 80,), Container(color: Colors.red, width: 100, height: 180,), Container(color: Colors.black, width: 60, height: 80,), Container(color: Colors.green, width: 60, height: 80,), ], ); ~~~ :-: ![](https://img.kancloud.cn/90/9a/909ad17a65cad573bca0c84c09b7fc72_828x1792.png) (a)Row 示例 :-: ![](https://img.kancloud.cn/9a/1b/9a1bd0067d1bbb03d5ab74f411afae86_828x1792.png) (b)Column 示例 圖 4 Row 與 Column 示例 可以看到,單純使用 Row 和 Column 控件,在子 Widget 的尺寸較小時,無法將容器填滿,視覺樣式比較難看。對于這樣的場景,我們可以通過 Expanded 控件,來制定分配規則填滿容器的剩余空間。 比如,我們希望 Row 組件(或 Column 組件)中的綠色容器與黃色容器均分剩下的空間,于是就可以設置它們的彈性系數參數 flex 都為 1,這兩個 Expanded 會按照其 flex 的比例(即 1:1)來分割剩余的 Row 橫向(Column 縱向)空間: ~~~ Row( children: <Widget>[ Expanded(flex: 1, child: Container(color: Colors.yellow, height: 60)), // 設置了 flex=1,因此寬度由 Expanded 來分配 Container(color: Colors.red, width: 100, height: 180,), Container(color: Colors.black, width: 60, height: 80,), Expanded(flex: 1, child: Container(color: Colors.green,height: 60),)/ 設置了 flex=1,因此寬度由 Expanded 來分配 ], ); ~~~ :-: ![](https://img.kancloud.cn/0e/d3/0ed3fba81215150607edddaafbe9b304_828x1792.png) 圖 5 Expanded 控件示例 于 Row 與 Column 而言,Flutter 提供了依據坐標軸的布局對齊行為,即根據布局方向劃分出主軸和縱軸:主軸,表示容器依次擺放子 Widget 的方向;縱軸,則是與主軸垂直的另一個方向。 :-: ![](https://img.kancloud.cn/61/01/610157c35f4457a7fffa2005ea144609_880x570.png) 圖 6 Row 和 Column 控件的主軸與縱軸 我們可以根據主軸與縱軸,設置子 Widget 在這兩個方向上的對齊規則 mainAxisAlignment 與 crossAxisAlignment。比如,主軸方向 start 表示靠左對齊、center 表示橫向居中對齊、end 表示靠右對齊、spaceEvenly 表示按固定間距對齊;而縱軸方向 start 則表示靠上對齊、center 表示縱向居中對齊、end 表示靠下對齊。 下圖展示了在 Row 中設置不同方向的對齊規則后的呈現效果: :-: ![](https://img.kancloud.cn/9f/3a/9f3a8a9e197b350f6c0aad6f5195fc87_3312x1792.png) 圖 7 Row 的主軸對齊方式 :-: ![](https://img.kancloud.cn/d8/fc/d8fc6d0aa98be8a6b1867b24a833b89b_2484x1792.png) 圖 8 Row 的縱軸對齊方式 Column 的對齊方式也是類似的,我就不再過多展開了。 這里需要注意的是,對于主軸而言,Flutter 默認是讓父容器決定其長度,即盡可能大,類似 Android 中的 match\_parent。 在上面的例子中,Row 的寬度為屏幕寬度,Column 的高度為屏幕高度。主軸長度大于所有子 Widget 的總長度,意味著容器在主軸方向的空間比子 Widget 要大,這也是我們能通過主軸對齊方式設置子 Widget 布局效果的原因。 如果想讓容器與子 Widget 在主軸上完全匹配,我們可以通過設置 Row 的 mainAxisSize 參數為 MainAxisSize.min,由所有子 Widget 來決定主軸方向的容器長度,即主軸方向的長度盡可能小,類似 Android 中的 wrap\_content: ~~~ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 由于容器與子 Widget 一樣寬,因此這行設置排列間距的代碼并未起作用 mainAxisSize: MainAxisSize.min, // 讓容器寬度與所有子 Widget 的寬度一致 children: <Widget>[ Container(color: Colors.yellow, width: 60, height: 80,), Container(color: Colors.red, width: 100, height: 180,), Container(color: Colors.black, width: 60, height: 80,), Container(color: Colors.green, width: 60, height: 80,), ], ) ~~~ :-: ![](https://img.kancloud.cn/d8/d9/d8d9cc480386bd11e60da51ddc081696_1656x1792.png) 圖 9 Row 的主軸大小 可以看到,我們設置了主軸大小為 MainAxisSize.min 之后,Row 的寬度變得和其子 Widget 一樣大,因此再設置主軸的對齊方式也就不起作用了。 ## 層疊 Widget 布局:Stack 與 Positioned 有些時候,我們需要讓一個控件疊加在另一個控件的上面,比如在一張圖片上放置一段文字,又或者是在圖片的某個區域放置一個按鈕。這時候,我們就需要用到層疊布局容器 Stack 了。 Stack 容器與前端中的絕對定位、Android 中的 Frame 布局非常類似,子 Widget 之間允許疊加,還可以根據父容器上、下、左、右四個角的位置來確定自己的位置。 **Stack 提供了層疊布局的容器,而 Positioned 則提供了設置子 Widget 位置的能力**。接下來,我們就通過一個例子來看一下 Stack 和 Positioned 的具體用法吧。 在這個例子中,我先在 Stack 中放置了一塊 300*300 的黃色畫布,隨后在 (18,18) 處放置了一個 50*50 的綠色控件,然后在 (18,70) 處放置了一個文本控件。 ~~~ Stack( children: <Widget>[ Container(color: Colors.yellow, width: 300, height: 300),// 黃色容器 Positioned( left: 18.0, top: 18.0, child: Container(color: Colors.green, width: 50, height: 50),// 疊加在黃色容器之上的綠色控件 ), Positioned( left: 18.0, top:70.0, child: Text("Stack 提供了層疊布局的容器 "),// 疊加在黃色容器之上的文本 ) ], ) ~~~ 試著運行一下,可以看到,這三個子 Widget 都按照我們預定的規則疊加在一起了。 :-: ![](https://img.kancloud.cn/bb/04/bb046cc53ea595a02a564a4387a99c36_828x1792.png) 圖 10 Stack 與 Positioned 容器示例 Stack 控件允許其子 Widget 按照創建的先后順序進行層疊擺放,而 Positioned 控件則用來控制這些子 Widget 的擺放位置。需要注意的是,Positioned 控件只能在 Stack 中使用,在其他容器中使用會報錯。 ## 總結 Flutter 的布局容器強大而豐富,可以將小型、單用途的基本視覺元素快速封裝成控件。今天我選取了 Flutter 中最具代表性,也最常用的幾類布局 Widget,與你介紹了構建一個界面精美的 App 所需要的布局概念。 接下來,我們簡單回顧一下今天的內容,以便加深理解與記憶: 首先,我們認識了單子容器 Container、Padding 與 Center。其中,Container 內部提供了間距、背景樣式等基礎屬性,為子 Widget 的擺放方式,及展現樣式都提供了定制能力。而 Padding 與 Center 提供的功能,則正如其名一樣簡潔,就是對齊與居中。 然后,我們深入學習了多子 Widget 布局中的 Row 和 Column,各子 Widget 間對齊的規則,以及容器自身擴充的規則,以及如何通過 Expanded 控件使用容器內部的剩余空間, 最后,我們學習了層疊布局 Stack,以及與之搭配使用的,定位子 Widget 位置的 Positioned 容器,你可以通過它們,實現多個控件堆放的布局效果。 通過今天的文章,相信你已經對如何搭建 App 的界面有了足夠的知識儲備,所以在下一篇文章中,我會通過一些實際的例子,帶你認識在 Flutter 中,如何通過這些基本控件與布局規則,實現好看的界面。 ## 思考題 最后,我給你留下一道思考題吧。 Row 與 Column 自身的大小是如何決定的?當它們嵌套時,又會出現怎樣的情況呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看