flutter listview 滾動到指定位置_Flutter 布局原理及實戰

1. Flutter UI架構

a828928b176595f68f6b023b2373348c.png

Flutter將視圖數據抽象成為三個部分,即Widget樹、Element樹和RenderObject樹。

  • Widget樹:控件的配置信息,不涉及渲染,更新代價極低。
  • RenderObject樹:真正的UI渲染樹,負責渲染UI,更新代價極大。
  • Element樹:Widget樹和RenderObject樹之間的粘合劑,負責將Widget樹的變更以最低的代價映射到RenderObject樹上。

2. Flutte布局原理

1. 源碼分析

RenderObject是Flutter真正的UI渲染樹,負責界面的測量,布局和繪制,Flutter頁面布局相關的源碼都在RenderObject及其子類中。

34138ce6fb90902ffa6a11550453b3cf.png

上圖是RenderObject類中和布局相關的屬性和方法.

  • constrainst屬性由直接父布局提供的布局約束(最大高度,最小高度,最大寬度,最小寬度),
  • layout方法由父RenderObject調用,計算當前RenderObject的布局,父RenderObject傳遞給子RenderObject約束信息,子RenderObject必須服從約束信息。如果父RenderObject需要子RenderObject的布局信息,parentUsesSize參數應該傳true,否則傳false。
  • performLayout:子類必須重寫的方法,計算當前RenderObject和子RenderObject的布局信息。
  • performResize:子類必須重寫的方法,僅使用約束更新RenderObject的布局。RenderConstrainedBox是ConstrainedBox對應的RenderObject,最多有一個子RenderObject, 如果子RenderoObject不為空,則對子RenderObject進行布局,并計算布局的大小。RenderFlex是Column和Row對應的RenderObject,可以包含多個子RenderObject, 如果子RenderoObject不為空,則對子RenderObject依次進行布局,并計算布局的大小。

2. Flutte布局原理總結

  1. RenderObject會通過它的父級獲得自身的約束。 約束實際上就是4個浮點類型的集合:最大/最小寬度,以及最大/最小高度。
  2. 然后,這個RenderObject將會逐個遍歷它的children列表。向子級傳遞約束子級之間的約束可能會有所不同),然后詢問它的每一個子級需要用于布局的大小。
  3. 然后,這個RenderObject就會對它子級的children逐個進行布局。(水平方向是x軸,豎直是y軸)
  4. 最后,RenderObject將會把它的大小信息向上傳遞至父RenderObject(包括其原始約束條件)。

3. Flutter布局限制

由于父RenderObject傳遞給子RenderObject約束信息,子RenderObject傳遞給父RenderObject大小信息,Flutter布局存在一些限制:

  • 一個RenderObject僅在其父級給其約束的情況下才能決定自身的大小。 這意味著RenderObject通常情況下不能任意獲得其想要的大小。
  • 一個RenderObject無法知道,也不需要決定其在屏幕中的位置。 因為它的位置是由其父級決定的。
  • 當輪到父級決定其大小和位置的時候,同樣的也取決于它自身的父級,所以,在不考慮整棵樹的情況下,幾乎不可能精確定義任何RenderObject的大小和位置。

4. Flutter布局實戰

1.線性布局

線性布局的子布局在主軸上長度不能設置無限大(double.infinity),因為線性布局給子布局在主軸上的最大長度的約束就是無限大(double.infinity),會導致無限大的子布局無法計算當前布局的大小,布局失敗。如下:

// 第一個子Container的高度設置為無限大,導致布局失敗Column(  children: [    Container(      width: 200.0,      height: double.infinity,      color: Colors.blue,    ),    Container(      width: 200.0,      height: 200.0,      color: Colors.red,    ),  ],);// 子Column的高度為無限大,導致布局失敗Column(  children: [    Column(      children: [        Container(          width: 200.0,          height: 200.0,          color: Colors.blue,        ),      ],    ),    Container(      width: 200.0,      height: 200.0,      color: Colors.red,    ),  ],);

如果想要讓子布局占滿全屏可以增加Expanded布局。如下:

Column(  children: [    Expanded(      child: Container(        width: 200.0,        height: double.infinity,        color: Colors.blue,      ),    ),    Container(      width: 200.0,      height: 200.0,      color: Colors.red,    ),  ],);Column(  children: [    Expanded(      child: Column(        children: [          Container(            width: 200.0,            height: 200.0,            color: Colors.blue,          ),        ],      ),    ),    Container(      width: 200.0,      height: 200.0,      color: Colors.red,    ),  ],);

2. 棧布局

棧布局的子布局設置相對位置推薦使用Padding代替Position,并把fit屬性設置StackFit.loose,構建時Stack會自適應大小,否則需要使用Container設置Stack和Position的大小;并且Padding默認對上下左右都有相對距離(0),但Position沒有默認的相對布局,如果忘記設置,會使Position的子布局無法自動換行或布局不顯示。

不推薦:

// Text無法自動換行// Container布局不顯示Stack(  children: [    Positioned(      top: 100.0,      child: Text(          '測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試'),    ),    Positioned(      top: 0.0,      child: Column(        children: [          Container(            height: 100.0,            width: double.infinity,            color: Colors.red,          ),        ],      ),    )  ],);

推薦:

Stack(  children: [    Padding(      padding: const EdgeInsets.only(top: 10.0),      child: Text(          '測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試'),    ),    Padding(      padding: const EdgeInsets.only(top: 0.0),      child: Column(        children: [          Container(            height: 100.0,            width: double.infinity,            color: Colors.red,          ),        ],      ),    )  ],);

3. 可滾動布局

可滾動布局在主軸方向上的長度是無限大,父布局需要轉遞給可滾動布局最大長度的約束。

Column(  children: [    Expanded(      child: ListView(        children: [          Text('測試'),        ],      ),    ),  ],);

橫向可滾動布局必須設置高度。

Column(  children: [    Container(      height: 200.0,      child: ListView(        scrollDirection: Axis.horizontal,        children: [          Text('測試'),        ],      ),    ),  ],);

可滾動布局嵌套可滾動布局被嵌套布局的shrinkWrap屬性必須設置為true,并且可以將physics屬性設置為NeverScrollableScrollPhysics()來解決滑動沖突。

ListView(  children: [    ListView(      shrinkWrap: true,      physics: NeverScrollableScrollPhysics(),      children: [        Text('測試'),      ],    ),  ],);

5. 總結

本文章通過源碼分析講述Flutter布局的過程,分析實戰中布局不顯示的原因,并給出Flutter布局的一些建議。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533691.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533691.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533691.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機的屏幕約是16平方分米嗎,小明的臥室有16平方分米對不對

小明的臥室有16平方分米對不對不對,應該是16平方米不對錯! 16平方分米太小了不對,那么小怎么可能住人。不正確應該是16平方米xiao ming de wo shi you 1 6 ping fang fen mi dui bu dui32平方分米涂上每平方分米的96克油漆,需要幾克32平方分米需要油漆30…

python引用傳遞_python 是值傳遞還是引用傳遞 知乎

展開全部 那要看數據類型了,21135261int,float,str這種就是傳值,list,dict,類的實例,自定義對象都是穿4102引用。 下面1653是示例代碼:def change(int1,float1,str1,dict1,obj1,list…

雷神開機logo更改_國產外星人雷神再發新品 911MT逐影者RTX2060光追游戲本評測

隨著NVIDIA發布了筆記本20系顯卡之后,宣示著全民進入了“RTX光線追蹤時代”,各種新款的游戲也紛紛宣布支持“光線追蹤”技術來吸引更多的玩家,似乎現在游戲本上沒有個“RTX”貼紙就已經不好意思跟別人打招呼了。說到2019年的RTX新品&#xff…

AJAX框架衣柜內部布局,?最合理的衣柜內部布局解析,3大細節不容小覷

時常有業主或者朋友問小輕,最合理的衣柜內部布局應該是怎樣的,確實這對于非業內人士一般都是不太清楚的,即使有的朋友已經有了豐富的生活經驗,甚至是業內人士也不一定對此完全了解。那么到底最合理的衣柜內部布局是怎樣的呢&#…

python爬取數據保存為csv時生成編號_將爬取到到數據以CSV格式存儲

CSV文件存儲 CSV,全稱為Comma-Separated Values,中文可以叫做逗號分隔值或字符分隔值,其文件以純文本形式存儲表格數據。該文件是一個字符序列,可以由任意數目的記錄組成,記錄間以某種換行符分隔。每條記錄由字段組成&…

博達3956交換機配置手冊_網絡設備維保淺談之交換機維保

隨著信息化的飛速發展,交換機作為信息流通的承載者,是應用最為廣泛的網絡設備之一,其作用不言而喻。因此,在日產使用中,要注意交換機這種核心的設備的維護與保養,以免引發故障。交換機運維需要注意哪些問題…

java cas原理_Java并發之原子變量及CAS算法-上篇

Java并發之原子變量及CAS算法-上篇編輯?概述本文主要講在Java并發編程的時候,如果保證變量的原子性,在JDK提供的類中是怎么保證變量原子性的呢?。對應Java中的包是:java.util.concurrent.atomic包下。因為涉及到了CAS算法&#x…

node ajax validator,使用validator.js對字符串數據進行驗證

validator.js是一個對字符串進行數據驗證和過濾的工具庫,同時支持Node端和瀏覽器端,github地址是https://github.com/chriso/validator.js主要API如下:驗證APIcontains(str, seed)驗證str中是否含有seedequals(str, comparison)驗證是否相等i…

css span 右端對齊_CSS標準文檔流

web頁面的制作,是個“流”,像水流一樣,必須從上往下,一點點的編織,不像畫畫,可以這個地方畫一個,另一個地方畫一個,隨意而為。標準文檔流的一些微觀現象1. 空白折疊現象1)標簽與標簽…

composer升級_Composer 使用姿勢與 Lumen 升級指南

Composer 使用姿勢這里主要說說 composer.json 和 composer.lock 文件的作用。composer.jsoncomposer.json 文件包含了項目的依賴和其它的一些元數據,使用 JSON format 編寫。當初次調用 composer install 時,Composer 會根據 composer.json 文件&#x…

服務器間傳文件$d,基于OpenSSH+WinSCP完成Windows服務器之間的文件傳輸

背景經常會遇到在不同服務器之間傳輸文件,Linux和Linux之間用命令rsync, windows和linux之間普遍是有圖形化界面的ftp軟件,老黃平時用的比較多的是FileZilla。Windows和Windows之間的話,90%都是在一臺機器復制,到另一臺…

dbgrideh 為什么只一行_Mysql性能優化:為什么count(*)這么慢?

導讀在開發中一定會用到統計一張表的行數,比如一個交易系統,老板會讓你每天生成一個報表,這些統計信息少不了sql中的count函數。但是隨著記錄越來越多,查詢的速度會越來越慢,為什么會這樣呢?Mysql內部到底是…

jmeter 高并發測試報告_JMeter分布式測試

一、為什么要使用分布式測試按照一般的壓力機配置,jmeter的GUI模式下(Windows),最多支持300左右的模擬請求線程,再大的話,容易造成卡頓、無響應等情況,這是限于jmeter其本身的機制和硬件配置。有時候為了盡量模擬業務場…

登陸攔截攔截ajax,過濾器實現登錄攔截需要注意的問題(AJAX請求的處理)

1.問題描述:最近自己在寫demo時遇到一個問題,在ajax請求時用Filter做登錄攔截,結果頁面不跳轉(Ajax是不能做轉發和重定向的)、、、、最終的最終在同事zt的提示下,恍然大悟,雖然很基本的問題,但也糾結了好久…

半圓陰影_六年級數學:怎么求陰影部分面積?正方形與半圓,割補法常考題

歡迎您來到方老師數學課堂,請點擊上方藍色字體,添加關注。所有的視頻內容,全部免費,請大家放心關注,放心訂閱。六年級數學:怎么求陰影部分面積?正方形與半圓,割補法常考題。大家先在…

c語言判斷整數_用c++編寫閏年的判斷基礎程序

其實c語言與c語言有太多共同的東西,學習過c語言再學習c語言就顯得輕而易舉。當然學過了c再去學習c語言也是有一些幫助的(但是個人不提倡先學習c在學c語言)。由于現在經常看見有關閏年的程序,風式各樣,眼花繚亂,些許凌亂&#xff0…

cat日志 搜索_大日志,看我如何對付你

在服務器接口測試中,我們經常會和各種日志打交道。一旦測試時服務端出現了問題,而單憑服務端的日志又不能發現問題原因的時候,往往開發要向我們測試人員詢問客戶端這邊的情況,希望看看我們能不能提供一些有用信息,如錯…

python編譯成dll文件_用vc生成可被python調用的dll文件

前提已經有.c 和.i文件 用swid編譯了.i文件生成了wrap.c文件和.py文件 vc創建dll工程 將.h加入到頭文件中.c文件和wrap.c文件添加到源文件中 將.i文件添加到工程目錄下 Tools->Options->Directories中修改include 和lib 添加python里的include 和libs 把\libs\python27.l…

加載gif動圖_GIF生成神器——ScreenToGif

每次需要做一個動圖展示時,總是感覺很頭疼。截圖吧,需要的圖片太多;錄視頻吧,文件太大;做動圖吧,太麻煩。今天推薦的這個軟件或許能夠解決大家這個困惑,今天推薦的是動圖生成神器——ScreenToGi…

vue底部選擇器_vue實現動態顯示與隱藏底部導航的方法分析

vue實現動態顯示與隱藏底部導航的方法分析本文實例講述了vue實現動態顯示與隱藏底部導航的方法。分享給大家供大家參考,具體如下:在日常項目中,總有幾個頁面是要用到底部導航的,總有那么些個頁面,是不需要底部導航的&a…