Flutter 常用佈局

移動的小太陽發表於2021-03-19

Flutter 常用佈局

在UI 的程式設計世界裡面,一個個view 都是巢狀在佈局裡面,最終呈現出合適的UI效果。今天就一起來看看 Flutter 中的佈局有哪些。

由於在Flutter 的世界中,一切都是Widget ,自然佈局也不例外。Flutter 提供了 31 種佈局 Widget,對佈局控制元件的劃分非常詳細,一些相同(或相似)的視覺效果可以通過多種佈局控制元件實現,因此佈局型別相比原生 Android、iOS 平臺多了不少。根據以往的經驗,可以把佈局分為幾類:單子Widget 佈局、多子Widget 佈局。

單子Widget 佈局

單子 Widget 佈局類容器比較簡單,一般用來對其唯一的子 Widget 進行樣式包裝,比如限制大小、新增背景色樣式、內間距、旋轉變換等。這一類佈局 Widget,包括 Container、Padding 與 Center 三種。

這些佈局都有哪些呢?Container、Padding 與 Center等 具體參考單子widget佈局

Container

Container 是最常用的佈局之一,可以通過設定 寬高、margin、padding、背景色、形狀、子widget的對齊方式等。

image.png

Padding

當只需要給 widget 設定padding,這時候可以使用更簡單的佈局--Padding。

image.png

Center

想要讓一個widget 在父容器居中,使用 Center就可以。

image.png

多子Widget 佈局

看完了三個常用的單子widget 佈局後,一定覺得很簡單,下面我們一起進入到多子widget 佈局的學習吧。 在Flutter 中,常用的多子widget 佈局有,Row、Column 與 Expanded。

Row

Row:表示的是一行,子widget 橫向排列,我們先看看Row中的建構函式

  Row({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,//主軸的對齊方式
    MainAxisSize mainAxisSize = MainAxisSize.max,//寬度,MainAxisSize.max表示佔滿父容器,MainAxisSize.min表示自適應,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,// 縱軸的對齊方式
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline = TextBaseline.alphabetic,
    List<Widget> children = const <Widget>[],
  }) 
複製程式碼

主軸:就是表示容器依次擺放子 Widget 的方向;縱軸,則是與主軸垂直的另一個方向。 我們來看個例子:

image.png

Column

Column:表示的是一列,子widget 橫向排列,我們先看看Column中的建構函式

  Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  })
複製程式碼

發現和Row完全一樣,使用方式也是一樣,這裡就不過多介紹了,

Expanded

單純使用 Row 和 Column 控制元件,在子 Widget 的尺寸較小時,無法將容器填滿,視覺樣式比較難看。對於這樣的場景,我們可以通過 Expanded 控制元件,來制定分配規則填滿容器的剩餘空間。相當Android LinearLayout 中的權重 layout_weight來設定widget 所佔剩餘控制元件的比重。

image.png

層疊 Widget 佈局:Stack 與 Positioned

Stack 容器與前端中的絕對定位、Android 中的 Frame 佈局非常類似,子 Widget 之間允許疊加,還可以根據父容器上、下、左、右四個角的位置來確定自己的位置。 Stack 提供了層疊佈局的容器,而 Positioned 則提供了設定子 Widget 位置的能力。

image.png

MaterialApp

是我們app開發中常用的符合MaterialApp Design設計理念的入口Widget,從原始碼可以看出該widget的構造方法中有多個引數. MaterialApp

MaterialApp({
  Key key,
  this.title = '', // 裝置用於為使用者識別應用程式的單行描述
  this.home, // 應用程式預設路由的小部件,用來定義當前應用開啟的時候,所顯示的介面
  this.color, // 在作業系統介面中應用程式使用的主色。
  this.theme, // 應用程式小部件使用的顏色。
  this.routes = const <String, WidgetBuilder>{}, // 應用程式的頂級路由表
  this.navigatorKey, // 在構建導航器時使用的鍵。
  this.initialRoute, // 如果構建了導航器,則顯示的第一個路由的名稱
  this.onGenerateRoute, // 應用程式導航到指定路由時使用的路由生成器回撥
  this.onUnknownRoute, // 當 onGenerateRoute 無法生成路由(initialRoute除外)時呼叫
  this.navigatorObservers = const <NavigatorObserver>[], // 為該應用程式建立的導航器的觀察者列表
  this.builder, // 用於在導航器上面插入小部件,但在由WidgetsApp小部件建立的其他小部件下面插入小部件,或用於完全替換導航器
  this.onGenerateTitle, // 如果非空,則呼叫此回撥函式來生成應用程式的標題字串,否則使用標題。
  this.locale, // 此應用程式本地化小部件的初始區域設定基於此值。
  this.localizationsDelegates, // 這個應用程式本地化小部件的委託。
  this.localeListResolutionCallback, // 這個回撥負責在應用程式啟動時以及使用者更改裝置的區域設定時選擇應用程式的區域設定。
  this.localeResolutionCallback, // 
  this.supportedLocales = const <Locale>[Locale('en', 'US')], // 此應用程式已本地化的地區列表 
  this.debugShowMaterialGrid = false, // 開啟繪製基線網格材質應用程式的網格紙覆蓋
  this.showPerformanceOverlay = false, // 開啟效能疊加
  this.checkerboardRasterCacheImages = false, // 開啟柵格快取影像的棋盤格
  this.checkerboardOffscreenLayers = false, // 開啟渲染到螢幕外點陣圖的圖層的棋盤格
  this.showSemanticsDebugger = false, // 開啟顯示框架報告的可訪問性資訊的覆蓋
  this.debugShowCheckedModeBanner = true, // 在選中模式下開啟一個小的“DEBUG”橫幅,表示應用程式處於選中模式
}) 
複製程式碼

裡面有很多的引數,在使用的時候可以根據需要選擇配置,不用太多,我們常用的是 :this.theme,this.home等

Scaffold

Scaffold 翻譯過來就是腳手架的意思,它實現了基本的 Material Design 視覺化佈局結構。此類提供了用於顯示drawer、snackbar和底部sheet的API。

const Scaffold({
  Key key,
  this.appBar, // 標題欄
  this.body,  // 用於顯示當前介面主要內容的Widget
  this.floatingActionButton, // 一個懸浮在body上的按鈕,預設顯示在右下角
  this.floatingActionButtonLocation, // 用於設定floatingActionButton顯示的位置
  this.floatingActionButtonAnimator, // floatingActionButton移動到一個新的位置時的動畫
  this.persistentFooterButtons, // 多狀態按鈕
  this.drawer, // 左側的抽屜選單
  this.endDrawer, //  右'側的抽屜選單
  this.bottomNavigationBar,// 底部導航欄。
  this.bottomSheet, // 顯示在底部的工具欄
  this.backgroundColor,// 內容的背景顏色
  this.resizeToAvoidBottomPadding = true, // 控制介面內容 body 是否重新佈局來避免底部被覆蓋,比如當鍵盤顯示的時候,重新佈局避免被鍵盤蓋住內容。
  this.primary = true,// Scaffold是否顯示在頁面的頂部
}) 
複製程式碼

看看例子:

Scaffold(
          appBar: AppBar(
            title: Text("單一widget佈局"),
            bottom: TabBar(
              tabs: [
                Text("Container"),
                Text("Padding"),
                Text("Center"),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              ContainerDemo(),
              PaddingDemo(),
              CenterDemo(),
            ],
          ),
        ),
複製程式碼

DefaultTabController

頂部導航元件TabBar,TabBar選項卡一般位於AppBar下方,通常和TabBar(頂部導航選項卡)一起使用的有TabBarView和TabController。

DefaultTabController({
    Key key,
    @required this.length,//Tab 的個數
    this.initialIndex = 0,
    @required this.child,//顯示的主要頁面內容
  })
複製程式碼

TabBar

const TabBar({
    Key key,
    @required this.tabs,//顯示的標籤內容,一般使用Tab物件,也可以是其他Widget
    this.controller,//TabController物件
    this.isScrollable = false,//是否可以滾動
    this.indicatorColor,//指示器顏色
    this.indicatorWeight = 2.0,//指示器的高度
    this.indicatorPadding = EdgeInsets.zero,//指示器底部的padding
    this.indicator,//指示器decoration,例如邊框等
    this.indicatorSize,//指示器大小的計算方式,TabBarIndicatorSize.tab:跟每個tab等寬,TabBarIndicatorSize.label:跟文字等寬
    this.labelColor,//選中label的顏色
    this.labelStyle,//選中label的樣式
    this.labelPadding,每個label的padding
    this.unselectedLabelColor,//未選中label的顏色
    this.unselectedLabelStyle,//未選中label的樣式
  }) 
複製程式碼

TabBarView

const TabBarView({
    Key key,
    @required this.children,//Tab頁內容元件的集合
    this.controller,//TabController物件
    this.physics,
  }) 
複製程式碼

看看例子:

Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            title: Text("單一widget佈局"),
            bottom: TabBar(
              tabs: [
                Text("Container"),
                Text("Padding"),
                Text("Center"),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              ContainerDemo(),
              PaddingDemo(),
              CenterDemo(),
            ],
          ),
        ),
      ),
    );
複製程式碼

相關文章