Flutter 佈局控制項完結篇

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

本文對Flutter的29種佈局控制項進行了總結分類,講解一些佈局上的優化策略,以及面對具體的佈局時,如何去選擇控制項。 ...


本文對Flutter的29種佈局控制項進行了總結分類,講解一些佈局上的優化策略,以及面對具體的佈局時,如何去選擇控制項。

1. 系列文章

  1. Flutter 佈局詳解
  2. Flutter 佈局(一)- Container詳解
  3. Flutter 佈局(二)- Padding、Align、Center詳解
  4. Flutter 佈局(三)- FittedBox、AspectRatio、ConstrainedBox詳解
  5. Flutter 佈局(四)- Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth詳解
  6. Flutter 佈局(五)- LimitedBox、Offstage、OverflowBox、SizedBox詳解
  7. Flutter 佈局(六)- SizedOverflowBox、Transform、CustomSingleChildLayout詳解
  8. Flutter 佈局(七)- Row、Column詳解
  9. Flutter 佈局(八)- Stack、IndexedStack、GridView詳解
  10. Flutter 佈局(九)- Flow、Table、Wrap詳解
  11. Flutter 佈局(十)- ListBody、ListView、CustomMultiChildLayout詳解

1.1 亂侃

前前後後也算是拖拖拉拉的寫了一些Flutter的文章,寫的也都比較粗略。最近工作調動,內部換了部門,一頓瞎忙活,也打亂了原本的分享計劃。

從我最開始接觸Flutter到現在,差不多四個多月了。在這段時間裡面,Flutter也發佈了Release Preview版本。各個技術網站本著先撥頭籌的心態,推廣了幾波,國內的人氣跟著也起來了不少。全世界Flutter開發人員中,國內從業者占據了很大的比重,這個現象本身並不能說明什麼,不過可以反映一點,有商業訴求吧。當然觀望的還是占絕大部分,除了一些個人開發者愛折騰外,也就是一些大的業務成熟到不能再成熟的團隊,內部消化人員去折騰這個了。

插個題外話,有感於最近的工作變動,這段時間胡思亂想的比較多。一門技術對程式員來說到底意味著什麼?如果不需要再為生計奔波,是否還會對目前已上手的技術感興趣?如果你現在的項目所需要的技術,對你個人而言毫無加成,只會浪費你的時間,讓你在已有的技術棧上漸行漸遠,你是否還會參與這個項目。只有極少數人會遇上逆天改命的項目,不管參與什麼項目,技術人員的立身之本始終是技術(高管或者打算換行的除外),技術的選型,除去時間效率後續維護等普適性的考慮要素外,排在第一位的始終應該是對自身的提高,扯的有些遠了哈。

1.2 本質

我數了一下我文章總結過的佈局控制項,總共有29種。乍看會覺得真雞毛的多,不乍看,也會覺得雞毛的真多。為什麼其他的移動平臺沒有這麼多佈局控制項呢?其實不然,其他平臺沒有這麼細分。

以Android平臺為例,最基礎的幾種佈局例如LinearLayout、RelativeLayout、ConstraintLayout等等。很多Flutter的控制項,對於Android來說,僅僅是一個屬性的設置問題。

再往上看,iOS、Android、Web這些平臺的佈局,其實最基本就那幾種,線性佈局、絕對佈局、相對佈局等等。Flutter也逃不出這些,那為什麼Flutter現在有這麼多佈局控制項呢?

  • 第一點,之前文章介紹過的,Flutter的理念是萬物皆為widget。這和Flutter的實現機制有關,而不是因為它在佈局上有什麼特殊性,這也是最主要的一點。

  • 第二點,我覺得是因為這是Flutter的初期,如果有經歷過一個技術的完整發展周期,就會明白,前期只是提供各種零件,只有商業支撐或者人員支撐足夠的時候,才會去優化零件。而現在就是這麼一種資源不足的狀態。各種組件可以合併的有很多,底層的實現機制不會變,只是再加一層即可,這也是可以造輪子的地方,例如封裝一套適用於Android、iOS或者Web人員的控制項庫等。

  • 第三點,跟初期相關,一套新的技術,各種東西不可能一下子全想明白,路總是走著走著才發現走歪了,就像一些控制項,可能一些地方合適,但是一些新的地方又不太合適,所以就再造一個,所以有些控制項看起來功能十分相似。

說了這麼多,我其實就想說明一點,Flutter現在還只是處在社會發展的初級階段,還處在溫飽問題都解決不了的狀態,想達到小康還需要很長的一段路要走。

2. 單節點控制項

單節點控制項,顧名思義就是只有一個節點的佈局控制項。這種控制項有多少個呢,我之前文章總結過的有18種,現階段還是不排除增加的可能,哈哈。

2.1 分類

在這小節里,我嘗試從多個維度去對這些控制項進行分類,希望這樣可以幫助大家理解。

2.1.1 按照繼承劃分

Flutter單節點佈局控制項繼承分類

上面是這18種控制項的父節點層面的繼承關係,唯一不同的一個控制項就是Container。所以按照是否繼承自SingleChildRenderObjectWidget的分類如下:

  • 繼承自StatelessWidget的控制項,有Container。
  • 繼承自SingleChildRenderObjectWidget的控制項,有Padding、Align、Center、FittedBox、AspectRatio、ConstrainedBox、Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth、LimitedBox、Offstage、OverflowBox、SizedBox、SizedOverflowBox、Transform、CustomSingleChildLayout。

Container是一個組合控制項,不是一個基礎控制項,這點從繼承關係就可以看出來。

2.1.2 按照功能是否單一划分

分類如下:

  • 功能不單一的控制項,Container、Transform、FittedBox、SizedOverflowBox。
  • 功能單一的控制項,有Padding、Align、Center、AspectRatio、ConstrainedBox、Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth、LimitedBox、Offstage、OverflowBox、SizedBox、CustomSingleChildLayout。

先在此處小結一下,可以看出Container的特殊之處了吧,為什麼Container這麼特殊了。這個特殊要從兩個層面去看。

  • 對於Flutter而言,Container是特殊的,因為它不是功能單一的控制項,是一個組合的控制項,所以它相對於Flutter是特殊的。
  • 對於移動端開發者而言,它不是特殊的,因為很多UI都是一些基礎功能組合的,這樣能讓開發者更方便的使用。

那能得出什麼結論呢?我個人覺得,Container這種組合的控制項會越來越多,也會有個人開發者去開發這種通用型的組合控制項,這是一個大趨勢,是Flutter走向易用的一小步。

2.1.3 按照功能劃分

在此處我按照定位、尺寸、繪製三部分來嘗試著去做功能的劃分,當然這個劃分並不絕對,仁者見仁吧。

  • 定位控制項:Container、Align、Center、FittedBox、Baseline、Transform。
  • 尺寸控制項:Container、FittedBox、AspectRatio、ConstrainedBox、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth、LimitedBox、SizedBox、SizedOverflowBox。
  • 繪製控制項:Container、Padding、Offstage、OverflowBox、SizedOverflowBox、Transform。

有一個控制項並沒有歸到這三類中,CustomSingleChildLayout可以自定義實現,此處不做分類。Baseline可以把它放到繪製裡面去,此處我按照調節文字的位置去做分類,這個大家知道就行,並不是說只能這麼劃分。

對於繪製控制項,其實分的有些雜,我把顯示相關的都歸到這裡,例如是否顯示、內邊距、是否超出顯示以及變形等等。

每一種大類,Flutter都提供了多種控制項。經過這麼劃分,可以看出很多控制項功能的交叉,很多時候一個屬性的事情,Flutter還是分出了一個控制項。

Flutter單節點佈局控制項功能分類

2.2 使用

單節點控制項雖然這麼多,但是大部分不會挨個去嘗試。對於大部分人而言,都是佛系的用法,一個控制項能夠使用,就一直用到死。

在佈局上,大方向還是不停的,把一張設計圖,拆成一棵樹,每個節點根據需要,選擇合適的控制項,然後從根部開始不停嵌套,佈局就完成了。

2.3 控制項的選擇

控制項種類繁多,真正使用的時候該如何去選擇呢?有萬金油的做法,不管啥都用Container,這也是很多初接觸的人經常乾的方式。這麼做的確可以按照設計圖把佈局給實現了,但是會涉及到一些性能上的問題。

控制項的選擇,按照控制項最小功能的標準去選擇。例如需要將子節點居中,可以使用Container設置alignment的方式,也可以使用Center。但是從功能上,Center是最小級別的,因此選擇它的話,額外的開銷會最小。

將UI實現了,這隻是最基本的,當達到這一步了,應該更多的去思考,如何更好的佈局,使得性能更高。

3. 多節點控制項

多節點控制項的種類就少了一些,雖然也有11種,但是功能和場景多了,所以選擇上反而會簡單一些。

3.1 分類

多節點控制項內部實現比單節點控制項複雜的多,會從繼承以及功能兩個方向去做分類。

3.1.1 按照繼承劃分

Flutter多節點佈局控制項繼承分類

從上圖可以看出,多節點佈局控制項基本上可以分為三條線

  • 繼承自BoxScrollView的控制項,有GridView以及ListView;
  • 繼承自MultiChildRenderObjectWidget的控制項,有Row、Column、Flow、Wrap、Stack、IndexedStack、ListBody、CustomMultiChildLayout八種;
  • 繼承自RenderObjectWidget的控制項,有Table一種。

之前介紹過,GridView和ListView的實現都是非常相似的,基本上就是silvers只包含一個Sliver(GridView為SilverGrid、ListVIew為SliverList)的CustomScrollView。 這也是為啥這兩元素都繼承自BoxScrollView的緣故。

MultiChildRenderObjectWidget類,官方解讀如下

A superclass for RenderObjectWidgets that configure RenderObject subclasses
that have a single list of children.

它只是一個含有單一list子節點的控制項,為什麼Table不需要繼承自MultiChildRenderObjectWidget呢?

這是因為Table的子節點是二維(橫豎)的,而MultiChildRenderObjectWidget提供的是一個一維的子節點管理,所以必須繼承自RenderObjectWidget。知道了這些過後,對繼承關係的理解會有更好的幫助。

3.1.2 按照功能劃分

這個對於多節點佈局控制項來說,還是比較難以劃分的,筆者試著做瞭如下劃分:

  • 列表:GridView、ListView;
  • 單列單行或者多列多行:Row、Column、Flow、Wrap、ListBody、Table;
  • 顯示位置相關:Stack、IndexedStack、CustomMultiChildLayout。

個人覺得這種分類方式不是特別的穩妥,但還是寫下來了,請大家仁者見仁。

GridView和ListView分為一類,一個是因為其實現非常的相似,另一個原因是這兩個控制項內容區域可以無限,不像其他控制項的內容區域都是固定的,因此將這兩個劃分為一類。

關於單列單行多列多行的,也並不是說很嚴格的,Row、Column、Table、ListBody可能會遵守這種劃分,Flow以及Wrap則是近似的多列多行。這種劃分絕對不是絕對的,只是個人的一種考量劃分方式。

3.2 使用

多節點控制項種類較少,而且功能重疊的很少,因此在使用上來說,還是簡單一些。比較常用的GridView、ListView、Row、Column、Stack,這幾個控制項基本上涵蓋了大部分的佈局了。

3.3 控制項的選擇

多節點控制項功能重疊的較少,因此選擇上,不會存在太多模凌兩可的問題,需要什麼使用什麼即可。

4. 性能優化

性能優化這塊兒,可能仁者見仁,並沒有一個統一的說法,畢竟現在Flutter各方面都還不完善。但是,大方向還是有的,儘量使用功能集更小的控制項,這個對於渲染效率上還是有所幫助的。

4.1 優化

在這裡我試著去列舉一些,並不一定都正確。

  • 對於單節點控制項,如果一個佈局多個控制項都可以完成,則使用功能最小的,可以參照上面控制項分類中的功能劃分來做取捨;
  • 對於多節點控制項,如果單節點控制項滿足需求的話,則去使用單節點控制項進行佈局;
  • 對於ListView,標準構造函數適用於條目比較少的情況,如果條目較多的話,儘量使用ListView.builder;
  • 對於GridView,如果需要展示大量的數據的話,儘量使用GridView.builder;
  • Flow、Wrap、Row、Column四個控制項,單純論效率的話,Flow是最高效的,但是使用起來是最複雜的;
  • 如果是單行或者單列的話,Row、Column比Table更高效;
  • Stack和CustomMultiChildLayout如果同時滿足需求的話,CustomMultiChildLayout在某些時候效率會更高一些,但是取決於Delegate的實現,且使用起來更加的複雜;

上面所列的比較雜,但是歸納起來,無非這幾點:

  • 功能越少的控制項,效率越高;
  • ListView以及GridView的builder構造函數效率更高;
  • 實現起來比較複雜的控制項,效率一般會更高。

4.2 選擇

控制項的選擇,個人覺得把握大方向就夠了。如果時間緊急,以實現效率最優先,如果時間充裕的話,可以按照一些優化細則,去做一些選擇。單純控制項層面,帶來性能上的改進畢竟十分有限。

5. 實戰

首先看一下實際的效果圖,這個是之前做工程中,比較複雜的一個界面吧,就算放到native上看,也是比較複雜的。

Flutter複雜頁面樣例

這個頁面中有不少自定義控制項,例如日期選擇、進度等。整體看著複雜,實現起來其實也還好。關於如何佈局拆解,之前文章有過介紹,在這裡不再闡述,訣竅就是一個字----拆。

5.1 關於自定義控制項

自定義控制項一般都是繼承自StatelessWidget、StatefulWidget。也有一些特殊的,例如上面的進度控制項,直接使用Canvas畫的。

對於需要更新狀態的,一般都是繼承自StatefulWidget,對於不需要更新狀態的,使用StatelessWidget即可,能夠使用StatelessWidget的時候,也儘量使用它,StatefulWidget在頁面更新的時候,會存在額外的開銷。

Flutter的自定義控制項,寫起來可能會比原生的更簡單,它更多的是一些基礎控制項的組合使用,而很少涉及到底層的一些重寫。

5.2 關於生命周期

這是很蛋疼的一個問題,一個純Flutter的App,類似於Android中的單Activity應用。某個具體的頁面就算去監聽native層的生命周期,也僅僅是獲取到base activity的,而無法獲取到頁面層級的。

5.3 感想

Flutter如果輪子足夠的話,還是非常吸引人的,在熟悉了這些基礎組件過後,編寫起來,速度會非常快。自定義控制項的實現,也比較簡單。但是,性能方面,還是存在比較大的問題,複雜頁面首次載入,速度還是比較慢。對於高端機型來說,整體流暢度很不錯,堪比原生的app,低端機型,表現就比較捉急吧。整體來說,Flutter表現還是挺不錯的,可以上手試試,把玩把玩吧。就是寫起來,寫著寫著就覺得噁心,是真的噁心的那種噁心,看著各種嵌套標簽,感覺被降維成了web開發。

近期看到一些基於Flutter的自動佈局解決方案,之前也有想過,完全可以基於Flutter做出佈局的工具,僅僅是拖拽就可以實現完成度非常高的佈局頁面。也得益於Flutter本身的思想和實現機制,web方面的很多東西,個人覺得都可以借鑒到Flutter上。單純從UI層來說,Flutter確實有自己獨特的地方。如果Flutter在最開始,就僅僅是一套跨平臺的UI的話,可能更容易被人們接受吧。

前幾天看了官方的camera插件,還是挺蛋疼的,對於國內的Android端來說,直接拿來商用幾乎是不可能的。插件基於camera2去實現,國內大部分廠商對於camera2的支持很差,一些很容易復現的crash也沒有去解決。

如果決定在現有項目中使用Flutter,則需要做好埋坑造輪子的覺悟。如果人力緊缺的話,不應該在這上面去投入,人力富餘的時候,可以投入人力跟進研究,讓業界覺得你們很棒很前沿。

6. 後話

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

7. 參考

  1. Flutter 佈局詳解

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

-Advertisement-
Play Games
更多相關文章
  • 解決在將Excel表格導入到SQL Server資料庫時出現:Text was truncated or one or more characters had no match in the target code 的錯誤。將Excel表中最長的那條記錄移到第二行(即第一條記錄所在行)即可解決導入失... ...
  • MySQL集群架構系列將討論MySQL集群架構的幾種最常見形式解決的問題,實現原理,存在的問題,以及環境搭建步驟。 本文主要討論MySQL架構關註的問題。 1.高可用的作用 在MySQL的高可用架構中,高可用的作用簡單來講就是保證整個架構的對外服務不會出現中斷,即通過技術手段避免單點故障引起架構整體 ...
  • MySQL的字元串是從1開始編號的,這與電腦編程語言有所不同,在MySQL中1代表第一個字元,-1代表最後一個字元,以此類推。 MySQL中百分號“%”代表的是任意個字元,下劃線“_”代表的是任意一個字元。 ...
  • 本文配置主從使用的操作系統是Centos7,資料庫版本是mysql5.7。 準備好兩台安裝有mysql的機器(mysql安裝教程鏈接) 主資料庫配置 每個從資料庫會使用一個MySQL賬號來連接主資料庫,所以我們要在主資料庫里創建一個賬號,並且該賬號要授予 REPLICATION SLAVE 許可權 創 ...
  • #創建資料庫create database ST CHARACTER set utf8;#創建用戶create user ST identified by '19980510';#授權用戶操作該資料庫grant all on ST.* to ST; #創建學生表create table Studen ...
  • 1.環境準備 RHEL7.4(最小化安裝) 64bit 2G 記憶體 (1G 記憶體編譯將近一個小時) 磁碟空間 15G 以上。 配置為本地yum 源 從MySQL5.7版本開始,安裝MySQL需要依賴 Boost 的C++擴展,而且只能是 1.59.0 版本; 2.cmake簡介 從mysql5.5起 ...
  • 大數據又稱黑暗數據,是指人腦無法處理的海量數據聚合成的信息資產,在民生、IT、金融、農業、通信等方面都有廣泛應用。未來5年大數據行業呈井噴趨勢,人才需求火爆,2018年大數據人才缺口更是高達900萬。以後想要做大數據相關的工作,需要學習哪些技術知識? 羅馬不是一天建成的,大數據工程師也不是短時間能鍛 ...
  • RDB RDB是將當前數據生成快照保存到硬碟上。 RDB的工作流程: 1. 執行bgsave命令,Redis父進程判斷當前是否存在正在執行的子進程,如RDB/AOF子進程,如果存在bgsave命令直接返回。 2. 父進程執行fork操作創建子進程,fork操作過程中父進程被阻塞。 3. 父進程for ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...