Flutter 佈局(五)- LimitedBox、Offstage、OverflowBox、SizedBox詳解

来源:https://www.cnblogs.com/holy-loki/archive/2018/10/06/9735059.html
-Advertisement-
Play Games

本文主要介紹Flutter佈局中的LimitedBox、Offstage、OverflowBox、SizedBox四種控制項,詳細介紹了其佈局行為以及使用場景,並對源碼進行了分析。 ...


本文主要介紹Flutter佈局中的LimitedBox、Offstage、OverflowBox、SizedBox四種控制項,詳細介紹了其佈局行為以及使用場景,並對源碼進行了分析。

1. LimitedBox

A box that limits its size only when it's unconstrained.

1.1 簡介

LimitedBox,通過字面意思,也可以猜測出這個控制項的作用,是限制類型的控制項。這種類型的控制項前面也介紹了不少了,這個是對最大寬高進行限制的控制項。

1.2 佈局行為

LimitedBox是將child限制在其設定的最大寬高中的,但是這個限定是有條件的。當LimitedBox最大寬度不受限制時,child的寬度就會受到這個最大寬度的限制,同理高度。

1.3 繼承關係

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > LimitedBox

1.4 示例代碼

Row(
  children: <Widget>[
    Container(
      color: Colors.red,
      width: 100.0,
    ),
    LimitedBox(
      maxWidth: 150.0,
      child: Container(
        color: Colors.blue,
        width: 250.0,
      ),
    ),
  ],
)

1.5 源碼解析

const LimitedBox({
  Key key,
  this.maxWidth = double.infinity,
  this.maxHeight = double.infinity,
  Widget child,
})

1.5.1 屬性解析

maxWidth:限定的最大寬度,預設值是double.infinity,不能為負數。

maxHeight:同上。

1.5.2 源碼

先不說其源碼,單純從其作用,前面介紹的SizedBox、ConstrainedBox都類似,都是通過強加到child的constraint,來達到相應的效果。

我們直接看其計算constraint的代碼

minWidth: constraints.minWidth,
maxWidth: constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth(maxWidth),
minHeight: constraints.minHeight,
maxHeight: constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight(maxHeight)

LimitedBox只是改變最大寬高的限定。具體的佈局代碼如下:

if (child != null) {
  child.layout(_limitConstraints(constraints), parentUsesSize: true);
  size = constraints.constrain(child.size);
} else {
  size = _limitConstraints(constraints).constrain(Size.zero);
}

根據最大尺寸,限制child的佈局,然後將自身調節到child的尺寸。

1.6 使用場景

使用場景是不可能清楚了,光是找例子,就花了不少時間。Flutter的一些冷門控制項,真的是除了官方的文檔,啥材料都木有。谷歌說這個很有用,還是一臉懵逼。這種控制項,也有其他的替代解決方案,LimitedBox可以達到的效果,ConstrainedBox都可以實現。

2. Offstage

A widget that lays the child out as if it was in the tree, but without painting anything, without making the child available for hit testing, and without taking any room in the parent.

2.1 簡介

Offstage的作用很簡單,通過一個參數,來控制child是否顯示,日常使用中也算是比較常用的控制項。

2.2 佈局行為

Offstage的佈局行為完全取決於其offstage參數

  • 當offstage為true,當前控制項不會被繪製在屏幕上,不會響應點擊事件,也不會占用空間;
  • 當offstage為false,當前控制項則跟平常用的控制項一樣渲染繪製;

另外,當Offstage不可見的時候,如果child有動畫,應該手動停掉,Offstage並不會停掉動畫。

2.3 繼承關係

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Offstage

2.4 示例代碼

Column(
  children: <Widget>[
    new Offstage(
      offstage: offstage,
      child: Container(color: Colors.blue, height: 100.0),
    ),
    new CupertinoButton(
      child: Text("點擊切換顯示"),
      onPressed: () {
        setState(() {
          offstage = !offstage;
        });
      },
    ),
  ],
)

當點擊切換按鈕的時候,可以看到Offstage顯示消失。

2.5 源碼解析

const Offstage({ Key key, this.offstage = true, Widget child })

2.5.1 屬性解析

offstage:預設為true,也就是不顯示,當為flase的時候,會顯示該控制項。

2.5.2 源碼

我們先來看下Offstage的computeIntrinsicSize相關的方法:

@override
double computeMinIntrinsicWidth(double height) {
    if (offstage)
      return 0.0;
    return super.computeMinIntrinsicWidth(height);
  }

可以看到,當offstage為true的時候,自身的最小以及最大寬高都會被置為0.0。

接下來我們來看下其hitTest方法:

  @override
  bool hitTest(HitTestResult result, { Offset position }) {
    return !offstage && super.hitTest(result, position: position);
  }

當offstage為true的時候,也不會去執行。

最後我們來看下其paint方法:

@override
  void paint(PaintingContext context, Offset offset) {
    if (offstage)
      return;
    super.paint(context, offset);
  }

當offstage為true的時候直接返回,不繪製了。

到此,跟上面所說的佈局行為對應上了。我們一定要清楚一件事情,Offstage並不是通過插入或者刪除自己在widget tree中的節點,來達到顯示以及隱藏的效果,而是通過設置自身尺寸、不響應hitTest以及不繪製,來達到展示與隱藏的效果。

2.6 使用場景

當我們需要控制一個區域顯示或者隱藏的時候,可以使用這個場景。其實也有其他代替的方法,但是成本會高很多,例如直接在tree上插入刪除,但是不建議這麼做。

3. OverflowBox

A widget that imposes different constraints on its child than it gets from its parent, possibly allowing the child to overflow the parent.

3.1 簡介

OverflowBox這個控制項,允許child超出parent的範圍顯示,當然不用這個控制項,也有很多種方式實現類似的效果。

3.2 佈局行為

當OverflowBox的最大尺寸大於child的時候,child可以完整顯示,當其小於child的時候,則以最大尺寸為基準,當然,這個尺寸都是可以突破父節點的。最後加上對齊方式,完成佈局。

3.3 繼承關係

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > OverflowBox

3.4 示例代碼

Container(
  color: Colors.green,
  width: 200.0,
  height: 200.0,
  padding: const EdgeInsets.all(5.0),
  child: OverflowBox(
    alignment: Alignment.topLeft,
    maxWidth: 300.0,
    maxHeight: 500.0,
    child: Container(
      color: Color(0x33FF00FF),
      width: 400.0,
      height: 400.0,
    ),
  ),
)

OverflowBox例子

當maxHeight大於height的時候,可以完全顯示下來,當maxHeight小於height的時候,則不會會被隱藏掉

3.5 源碼解析

構造函數如下:

const OverflowBox({
    Key key,
    this.alignment = Alignment.center,
    this.minWidth,
    this.maxWidth,
    this.minHeight,
    this.maxHeight,
    Widget child,
  })

3.5.1 屬性解析

alignment:對齊方式。

minWidth:允許child的最小寬度。如果child寬度小於這個值,則按照最小寬度進行顯示。

maxWidth:允許child的最大寬度。如果child寬度大於這個值,則按照最大寬度進行展示。

minHeight:允許child的最小高度。如果child高度小於這個值,則按照最小高度進行顯示。

maxHeight:允許child的最大高度。如果child高度大於這個值,則按照最大高度進行展示。

其中,最小以及最大寬高度,如果為null的時候,就取父節點的constraint代替。

3.5.2 源碼

OverflowBox的源碼很簡單,我們先來看一下佈局代碼:

if (child != null) {
  child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
  alignChild();
}

如果child不為null,child則會按照計算出的constraints進行尺寸的調整,然後對齊。

至於constraints的計算,則還是上面的邏輯,如果設置的有的話,就取這個值,如果沒有的話,就拿父節點的。

3.6 使用場景

有時候設計圖上出現的角標,會超出整個模塊,可以使用OverflowBox控制項。但我們應該知道,不使用這種控制項,也可以完成佈局,在最外麵包一層,也能達到一樣的效果。具體實施起來哪個比較方便,同學們自行取捨。

4. SizedBox

A box with a specified size.

4.1 簡介

比較常用的一個控制項,設置具體尺寸。

4.2 佈局行為

SizedBox佈局行為相對較簡單:

  • child不為null時,如果設置了寬高,則會強制把child尺寸調到此寬高;如果沒有設置寬高,則會根據child尺寸進行調整;
  • child為null時,如果設置了寬高,則自身尺寸調整到此寬高值,如果沒設置,則尺寸為0;

4.3 繼承關係

Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > SizedBox

4.4 示例代碼

Container(
  color: Colors.green,
  padding: const EdgeInsets.all(5.0),
  child: SizedBox(
    width: 200.0,
    height: 200.0,
    child: Container(
      color: Colors.red,
      width: 100.0,
      height: 300.0,
    ),
  ),
)

4.5 源碼解析

構造函數

const SizedBox({ Key key, this.width, this.height, Widget child })

4.5.1 屬性解析

width:寬度值,如果具體設置了,則強制child寬度為此值,如果沒設置,則根據child寬度調整自身寬度。

height:同上。

4.5.2 源碼

SizedBox內部是通過RenderConstrainedBox來實現的。具體的源碼就不解析了,總體思路是,根據寬高值算好一個constraints,然後強制應用到child上。

4.6 使用場景

這個控制項,很多場景可以使用。但是,可以替代它的控制項也有不少,例如Container、ConstrainedBox等。而且SizedBox就是ConstrainedBox的一個特例。還是那句話,精簡啊,多提供一些常用的,不要提供一大堆重覆的,場景很少的控制項。

5. 後話

筆者建了一個Flutter學習相關的項目,Github地址,裡面包含了筆者寫的關於Flutter學習相關的一些文章,會定期更新,文章中的代碼也在這個項目中,歡迎大家關註。

6. 參考

  1. LimitedBox class
  2. Offstage class
  3. OverflowBox class
  4. SizedBox class

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

-Advertisement-
Play Games
更多相關文章
  • 前言: Mapreduce程式的效率的瓶頸在於兩點: MapReduce優化方法 數據輸入: (1)合併小文件:在執行任務前將小文件進行合併 (2)採用CombineTextInputformat來作為輸入,解決輸入端大量小文件的場景。將多個小文件從邏輯上規划到一個切片中,這樣,多個小文件就可以交給 ...
  • 現如今,數據增長速度快於處理速度,唯一的解決方案是在大型集群上並行化,而且這種技術以及廣泛應用於企業和網路行業。本章主要內容有:講解數據流與傳統的網路編程的區別、MapReduce的局限性、Spark computing engine、Matrix operations on Spark等。 資源下 ...
  • 很多初學者在剛剛接觸大數據的時候會有很多疑惑,比如對MapReduce、Storm、Spark三個計算框架的理解經常會產生混亂。 哪一個適合對大量數據進行處理?哪一個又適合對實時的流數據進行處理?又該如何來區分他們呢? 我對比整理了這3個計算框架的基本知識,大家可以瞭解一下以便對這個3個計算框架有一 ...
  • 作者:天山老妖S 鏈接:http://blog.51cto.com/9291927 一、字元集與編碼 1、字元集簡介 字元(Character)是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。字元集(Character set)是多個字元的集合,字元集種類較多,每個字元集包含的字 ...
  • 前面在介紹列表視圖和網格視圖時,它們的適配器代碼都存在視圖持有者ViewHolder,因為Android對列表類視圖提供了回收機制,如果某些列表項在屏幕上看不到了,則系統會自動回收相應的視圖對象。隨著用戶的下拉或者上拉手勢,已經被回收的列表項要重新載入到界面上,倘若每次載入都得從頭創建視圖對象,勢必 ...
  • 下麵舉Android的Browser源碼通過git保存到github上 首先在github.com官網new repository一個倉庫 在Repository name哪裡填入Browser然後創建 這時候會生成一個地址,這個就是你的倉庫地址。 例如我的:https://github.com/g ...
  • How to get out of Fast Factory Boot Mode(FFBM). ...
  • ListView現在已經很少被使用,但還是在這裡列出來說一下,有時候我們僅僅需要改變listView的某個Item,如果調用adapter的notifyDataSetChanged()方法效率不高,並且可能會出現內容閃動,那麼我們怎麼刷新某一個特定的item呢? 在這裡我們以刷新第一個item為例, ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...