Flutter 中有兩種布局模型:
從網站建設到定制行業解決方案,為提供網站設計制作、成都網站設計服務體系,各種行業企業客戶提供網站建設解決方案,助力業務快速發展。成都創新互聯公司將不斷加快創新步伐,提供優質的建站服務。
基于 RenderBox 的盒模型布局。
基于 Sliver ( RenderSliver ) 按需加載列表布局。
通??蓾L動組件的子組件可能會非常多、占用的總高度也會非常大;如果要一次性將子組件全部構建出將會非常昂貴!為此,Flutter中提出一個Sliver(中文為“薄片”的意思)概念,Sliver 可以包含一個或多個子組件。Sliver 的主要作用是配合:加載子組件并確定每一個子組件的布局和繪制信息,如果 Sliver 可以包含多個子組件時,通常會實現按需加載模型。
只有當 Sliver 出現在視口中時才會去構建它,這種模型也稱為“基于Sliver的列表按需加載模型”。可滾動組件中有很多都支持基于Sliver的按需加載模型,如 ListView 、 GridView ,但是也有不支持該模型的,如 SingleChildScrollView 。
Flutter 中的可滾動主要由三個角色組成: Scrollable 、 Viewport 和 Sliver :
具體布局過程:
比如有一個 ListView,大小撐滿屏幕,假設它有 100 個列表項(都是RenderBox)且每個列表項高度相同,結構如圖6-1所示:
圖中白色區域為設備屏幕,也是 Scrollable 、 Viewport 和 Sliver 所占用的空間,三者所占用的空間重合,父子關系為:Sliver 父組件為 Viewport,Viewport的 父組件為 Scrollable 。注意ListView 中只有一個 Sliver,在 Sliver 中實現了子組件的按需加載。
其中頂部和底部灰色的區域為 cacheExtent,它表示預渲染的高度,需要注意這是在可視區域之外,如果 RenderBox 進入這個區域內,即使它還未顯示在屏幕上,也是要先進行構建的,預渲染是為了后面進入 Viewport 的時候更絲滑。cacheExtent 的默認值是 250,在構建可滾動列表時我們可以指定這個值,這個值最終會傳給 Viewport。
用于處理滑動手勢,確定滑動偏移,滑動偏移變化時構建 Viewport,我們看一下其關鍵的屬性:
在可滾動組件的坐標描述中,通常將滾動方向稱為主軸,非滾動方向稱為縱軸。由于可滾動組件的默認方向一般都是沿垂直方向,所以默認情況下主軸就是指垂直方向,水平方向同理。
Viewport 比較簡單,用于渲染當前視口中需要顯示 Sliver。
需要注意的是:
Sliver 主要作用是對子組件進行構建和布局,比如 ListView 的 Sliver 需要實現子組件(列表項)按需加載功能,只有當列表項進入預渲染區域時才會去對它進行構建和布局、渲染。
Sliver 對應的渲染對象類型是 RenderSliver,RenderSliver 和 RenderBox 的相同點是都繼承自 RenderObject 類,不同點是在布局的時候約束信息不同。RenderBox 在布局時父組件傳遞給它的約束信息對應的是 BoxConstraints ,只包含最大寬高的約束;而 RenderSliver 在布局時父組件(列表)傳遞給它的約束是對應的是 SliverConstraints 。關于 Sliver 的布局協議,我們將在本章最后一節中介紹。
幾乎所有的可滾動組件在構造時都能指定 scrollDirection (滑動的主軸)、 reverse (滑動方向是否反向)、 controller 、 physics 、 cacheExtent ,這些屬性最終會透傳給對應的 Scrollable 和 Viewport,這些屬性我們可以認為是可滾動組件的通用屬性,后續再介紹具體的可滾動組件時將不再贅述。
可滾動組件都有一個 controller 屬性,通過該屬性我們可以指定一個 ScrollController 來控制可滾動組件的滾動,比如可以通過ScrollController來同步多個組件的滑動聯動。由于 ScrollController 是需要結合可滾動組件一起工作,所以本章中,我們會在介紹完 ListView 后詳細介紹 ScrollController。
Scrollbar是一個Material風格的滾動指示器(滾動條),如果要給可滾動組件添加滾動條,只需將Scrollbar作為可滾動組件的任意一個父級組件即可,如:
Scrollbar 和 CupertinoScrollbar 都是通過監聽滾動通知來確定滾動條位置的。關于的滾動通知的詳細內容我們將在本章最后一節中專門介紹。
CupertinoScrollbar是 iOS 風格的滾動條,如果你使用的是Scrollbar,那么在iOS平臺它會自動切換為CupertinoScrollbar
對其子項施加不同約束的widget,它可能允許子項溢出父級。
下一節:Layout組件之SizedOverflowBox
在出現布局錯誤時能盡快找到錯誤原因。
以下是對關鍵內容的翻譯和注解。
flutter的布局模型是“一步布局模型”(one-pass layout model),在渲染樹中,向下treewalk傳遞給子 盒約束,然后再向上treewalk將計算好的幾何形狀(比如高度、寬度等)傳遞給父。我理解one-pass layout model就是一遍就將布局計算好。不會多次treewalk去計算布局,或多次重繪(repaint)并多次計算布局。
計算的好的幾何形狀必須符合盒約束的要求。
盒約束有四個值,minWidth,maxWidth,minHeight,maxHeight,符合盒約束的意思就是說 計算出的寬高必須在最大值和最小值之間 。
我猜測,在將盒約束向子傳遞的過程中,子會根據父的盒約束,設置自己的盒約束,而不是單純的繼承父的盒約束。稍后結合Flex布局可以解釋。
盒約束的最小值和最大值相等。因此在tight約束下的子的高寬將等于父的高寬,也就是說子是緊緊(tight)貼著父的。
盒約束的最小值為0,也就是說子可以是小于盒約束最大值的任何值,也就是說子是不緊貼(松的,loose)父的。
盒約束的最大值不是infinite(無窮大)
盒約束的最大值是infinite(無窮大)
盒約束的最小值是infinite(無窮大),他的子的寬或高只能取無窮大。
子的寬高(Size)符合盒約束的要求。
以下摘抄原文檔并翻譯,并加以分析。為了關注要點, 忽略crossAxis方向(水平方向)的處理 。
以下圖為Column布局實例。
給column布局進行了以下6步操作
首先給每個非flex子元素,設置豎直方向unbounded(無界)的盒約束。結合圖片,也就是將1、2兩個子設置好豎直方向無界的盒約束。示例中1和2設置了高度,因此一共占用高度是5+3=8.
按flex的比例給flex元素分配剩余的空間。因為示例只有一個flex元素,即3號元素,因此將占有剩余全部空間,高度是20-5-3 = 12。
在第二步中分配好空間的flex元素,給他設置的盒約束不是豎直方向unbounded(給非flex元素設置的是豎直方向unbounded),而是有界的盒約束,盒約束的maxHeight是12,即第二步中被分配的高度。
水平方向不解釋了。高度設置完了他去設置寬度。
Column組件的總高度是由mainAxisSize屬性決定的,如果值是MainAxisSize.max,Column的高度就是Column的盒約束的maxHeight值,示例中我們給Column設置了高度為20的bounded盒約束,假設Column.mainAxisSize=MainAxisSize.max,那么Column的高度就是20.如果mainAxisSize=MainAxisSize.min,Column的高度將由其子元素的高度和決定。假設3號flex元素不設置成flex元素,而是固定高度為8,那么Column的高度就是5+3+8=16.
設置子元素的位置,即設置靠左,靠右,居中,分散等,與本示例關系不大。
根據第一步,inner column被outer column設置了無界(unbounded)的盒約束,Column會緊包children,而inner column的Expanded要撐開以占用inner column的剩余空間,這就沖突了。
解決方案:給inner column設置有界的盒約束即可。比如給inner column外包一層有高度的Container。
下面這種方案,給inner column包一層Expanded也可以,是因為在outer column中,Expanded會被設置成有界的盒約束(結合第三步),因此Expanded就可以向外擴展(expand)了。
網站欄目:flutterbox的簡單介紹
標題網址:http://vcdvsql.cn/article40/dsdeeeo.html
成都網站建設公司_創新互聯,為您提供外貿建站、用戶體驗、品牌網站設計、品牌網站制作、響應式網站、面包屑導航
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯