新聞中心
Flutter 可滾動組件 之 SingleChildScrollView (十五)
SingleChildScrollView 源碼定義如下:
鼓樓網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,鼓樓網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為鼓樓近千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請找那個售后服務(wù)好的鼓樓做網(wǎng)站的公司定做!
需要注意的是, 通常 SingleChildScrollView 只應(yīng)在期望的內(nèi)容不會超過屏幕太多時使用 ,這是因為 SingleChildScrollView 不支持基于 Sliver 的延遲加載模型,所以如果預(yù)計視口可能包含超出屏幕尺寸太多的內(nèi)容時,那么使用 SingleChildScrollView 將會非常昂貴(性能差),此時應(yīng)該使用一些支持Sliver延遲加載的可滾動組件,如 ListView 。
示例1
下面是一個將大寫字母 A-Z 沿垂直方向顯示的例子,由于垂直方向空間會超過屏幕視口高度,所以我們使用SingleChildScrollView:
示例2
示例3 - 橫向滾動
Flutter 之 滾動監(jiān)聽及控制(十九)
ListView、GridView的組件控制器是ScrollController,我們可以通過它來獲取視圖的滾動信息,并且可以調(diào)用里面的方法來更新視圖的滾動位置。
ScrollController構(gòu)造函數(shù)如下:
ScrollController常用的屬性和方法:
ScrollController間接繼承自Listenable,我們可以根據(jù)ScrollController來監(jiān)聽滾動事件,如:
示例
我們創(chuàng)建一個ListView,當(dāng)滾動位置發(fā)生變化時,我們先打印出當(dāng)前滾動位置,然后判斷當(dāng)前位置是否超過1000像素,如果超過則在屏幕右下角顯示一個“返回頂部”的按鈕,該按鈕點擊后可以使ListView恢復(fù)到初始位置;如果沒有超過1000像素,則隱藏“返回頂部”按鈕。
ScrollPosition是用來保存可滾動組件的滾動位置的。一個ScrollController對象可以同時被多個可滾動組件使用,ScrollController會為每一個可滾動組件創(chuàng)建一個ScrollPosition對象,這些ScrollPosition保存在ScrollController的positions屬性中(ListScrollPosition)。ScrollPosition是真正保存滑動位置信息的對象,offset只是一個便捷屬性
一個 ScrollController 雖然可以對應(yīng)多個可滾動組件,但是有一些操作,如讀取滾動位置 offset ,則需要一對一!但是我們?nèi)匀豢梢栽谝粚Χ嗟那闆r下,通過其它方法讀取滾動位置,舉個例子,假設(shè)一個 ScrollController 同時被兩個可滾動組件使用,那么我們可以通過如下方式分別讀取他們的滾動位置:
我們可以通過 controller.positions.length 來確定 controller 被幾個可滾動組件使用。
ScrollPosition 有兩個常用方法: animateTo() 和 jumpTo() ,它們是真正來控制跳轉(zhuǎn)滾動位置的方法, ScrollController 的這兩個同名方法,內(nèi)部最終都會調(diào)用 ScrollPosition 的。
我們來介紹一下 ScrollController 的另外三個方法:
當(dāng) ScrollController 和可滾動組件關(guān)聯(lián)時,可滾動組件首先會調(diào)用 ScrollController 的 createScrollPosition() 方法來創(chuàng)建一個 ScrollPosition 來存儲滾動位置信息,接著,可滾動組件會調(diào)用 attach() 方法,將創(chuàng)建的 ScrollPosition 添加到 ScrollController 的 positions 屬性中,這一步稱為“注冊位置”,只有注冊后 animateTo() 和 jumpTo() 才可以被調(diào)用。
當(dāng)可滾動組件銷毀時,會調(diào)用 ScrollController 的 detach() 方法,將其 ScrollPosition 對象從 ScrollController 的 positions 屬性中移除,這一步稱為“注銷位置”,注銷后 animateTo() 和 jumpTo() 將不能再被調(diào)用。
需要注意的是, ScrollController 的 animateTo() 和 jumpTo() 內(nèi)部會調(diào)用所有 ScrollPosition 的 animateTo() 和 jumpTo() ,以實現(xiàn)所有和該 ScrollController 關(guān)聯(lián)的可滾動組件都滾動到指定的位置。
Flutter Widget樹中子Widget可以通過發(fā)送通知(Notification)與父(包括祖先)Widget通信。父級組件可以通過NotificationListener組件來監(jiān)聽自己關(guān)注的通知
可滾動組件在滾動時會發(fā)送 ScrollNotification 類型的通知, ScrollBar 正是通過監(jiān)聽滾動通知來實現(xiàn)的。通過 NotificationListener 監(jiān)聽滾動事件和通過 ScrollController 有兩個主要的不同:
示例
下面,我們監(jiān)聽ListView的滾動通知,然后顯示當(dāng)前滾動進度百分比:
在接收到滾動事件時,參數(shù)類型為ScrollNotification,它包括一個metrics屬性,它的類型是ScrollMetrics,該屬性包含當(dāng)前ViewPort及滾動位置等信息:
Flutter:手把手教你使用滾動型列表組件:ListView
ListView的基礎(chǔ)創(chuàng)建使用有三種方式:
通過默認(rèn)構(gòu)造函數(shù)來創(chuàng)建列表,應(yīng)用場景 = 短列表
這種方式創(chuàng)建的列表存在一個問題:對于那些長列表或者需要較昂貴渲染開銷的子組件,即使還沒有出現(xiàn)在屏幕中但仍然會被ListView所創(chuàng)建,這將是一項較大的開銷,使用不當(dāng)可能引起性能問題甚至卡頓。
長列表
列表子項之間需要分割線
ListView的進階使用主要包括:下拉刷新 上拉加載
在Flutter中,ListView結(jié)合RefreshIndicator組件實現(xiàn)下拉刷新
通過包裹一層RefreshIndicator,自定義onRefresh回調(diào)方法實現(xiàn)
方式有兩種:
通過ListView.controller屬性可以判斷ListView是否滑動到了底部,再進行上拉加載
NotificationListener是一個Widget,可監(jiān)聽子Widget發(fā)出的Notification
ListView在滑動時中會發(fā)出ScrollNotification類型的通知,可通過監(jiān)聽該通知得到ListView的滑動狀態(tài),判斷是否滑動到了底部,從而進行上拉加載
NotificationListener有一個onNotification屬性,定義了監(jiān)聽的回調(diào)方法,通過它來處理加載更多邏輯
不定期分享關(guān)于 安卓開發(fā) 的干貨,追求 短、平、快 ,但 卻不缺深度 。
【Flutter】圖片、內(nèi)容、滾動空間溢出調(diào)整
空間超出提示
注釋 :Flutter Incorrect use of ParentDataWidget
問題原因:Expanded、Flexible等組件,在“Container、Padding、Stack”組件中導(dǎo)致的。
解決方案:保持: Expanded、Flexible 只在 Row、Column 等組件內(nèi),不在其他組件內(nèi)使用。
控件Row有一個水平的布局方向,但是內(nèi)容已經(jīng)超出了可顯示的范圍。
建議我們使用有彈性的控件比如Expanded代替,或者使用可裁剪的控件ClipRect代替,還可以使用具體滾動屬性的控件比如ListView代替
1、類似圖片加載失敗,然后溢出擠壓空間,可以用Container包裹一下
直接使用,如果圖片地址失效,就會溢出
直接使用,圖片鏈接失效引起
2、類似這種超出
A RenderFlex overflowed by 48 pixels on the right.
3、類似這種Column滾動超出!
實現(xiàn)頁面滑動需要用到SingleChildScrollView組件,SingleChildScrollView和Android中ScrollView類似
問題原因:Expanded、Flexible等組件,在“Container、Padding、Stack”組件中導(dǎo)致的。
解決方案:保持:Expanded、Flexible只在Row、Column等組件內(nèi),不在其他組件內(nèi)使用。
Flutter 之 可滾動組件 -- 理論知識點(十四)
Flutter 中有兩種布局模型:
基于 RenderBox 的盒模型布局。
基于 Sliver ( RenderSliver ) 按需加載列表布局。
通??蓾L動組件的子組件可能會非常多、占用的總高度也會非常大;如果要一次性將子組件全部構(gòu)建出將會非常昂貴!為此,F(xiàn)lutter中提出一個Sliver(中文為“薄片”的意思)概念,Sliver 可以包含一個或多個子組件。Sliver 的主要作用是配合:加載子組件并確定每一個子組件的布局和繪制信息,如果 Sliver 可以包含多個子組件時,通常會實現(xiàn)按需加載模型。
只有當(dāng) Sliver 出現(xiàn)在視口中時才會去構(gòu)建它,這種模型也稱為“基于Sliver的列表按需加載模型”??蓾L動組件中有很多都支持基于Sliver的按需加載模型,如 ListView 、 GridView ,但是也有不支持該模型的,如 SingleChildScrollView 。
Flutter 中的可滾動主要由三個角色組成: Scrollable 、 Viewport 和 Sliver :
具體布局過程:
比如有一個 ListView,大小撐滿屏幕,假設(shè)它有 100 個列表項(都是RenderBox)且每個列表項高度相同,結(jié)構(gòu)如圖6-1所示:
圖中白色區(qū)域為設(shè)備屏幕,也是 Scrollable 、 Viewport 和 Sliver 所占用的空間,三者所占用的空間重合,父子關(guān)系為:Sliver 父組件為 Viewport,Viewport的 父組件為 Scrollable 。注意ListView 中只有一個 Sliver,在 Sliver 中實現(xiàn)了子組件的按需加載。
其中頂部和底部灰色的區(qū)域為 cacheExtent,它表示預(yù)渲染的高度,需要注意這是在可視區(qū)域之外,如果 RenderBox 進入這個區(qū)域內(nèi),即使它還未顯示在屏幕上,也是要先進行構(gòu)建的,預(yù)渲染是為了后面進入 Viewport 的時候更絲滑。cacheExtent 的默認(rèn)值是 250,在構(gòu)建可滾動列表時我們可以指定這個值,這個值最終會傳給 Viewport。
用于處理滑動手勢,確定滑動偏移,滑動偏移變化時構(gòu)建 Viewport,我們看一下其關(guān)鍵的屬性:
在可滾動組件的坐標(biāo)描述中,通常將滾動方向稱為主軸,非滾動方向稱為縱軸。由于可滾動組件的默認(rèn)方向一般都是沿垂直方向,所以默認(rèn)情況下主軸就是指垂直方向,水平方向同理。
Viewport 比較簡單,用于渲染當(dāng)前視口中需要顯示 Sliver。
需要注意的是:
Sliver 主要作用是對子組件進行構(gòu)建和布局,比如 ListView 的 Sliver 需要實現(xiàn)子組件(列表項)按需加載功能,只有當(dāng)列表項進入預(yù)渲染區(qū)域時才會去對它進行構(gòu)建和布局、渲染。
Sliver 對應(yīng)的渲染對象類型是 RenderSliver,RenderSliver 和 RenderBox 的相同點是都繼承自 RenderObject 類,不同點是在布局的時候約束信息不同。RenderBox 在布局時父組件傳遞給它的約束信息對應(yīng)的是 BoxConstraints ,只包含最大寬高的約束;而 RenderSliver 在布局時父組件(列表)傳遞給它的約束是對應(yīng)的是 SliverConstraints 。關(guān)于 Sliver 的布局協(xié)議,我們將在本章最后一節(jié)中介紹。
幾乎所有的可滾動組件在構(gòu)造時都能指定 scrollDirection (滑動的主軸)、 reverse (滑動方向是否反向)、 controller 、 physics 、 cacheExtent ,這些屬性最終會透傳給對應(yīng)的 Scrollable 和 Viewport,這些屬性我們可以認(rèn)為是可滾動組件的通用屬性,后續(xù)再介紹具體的可滾動組件時將不再贅述。
可滾動組件都有一個 controller 屬性,通過該屬性我們可以指定一個 ScrollController 來控制可滾動組件的滾動,比如可以通過ScrollController來同步多個組件的滑動聯(lián)動。由于 ScrollController 是需要結(jié)合可滾動組件一起工作,所以本章中,我們會在介紹完 ListView 后詳細介紹 ScrollController。
Scrollbar是一個Material風(fēng)格的滾動指示器(滾動條),如果要給可滾動組件添加滾動條,只需將Scrollbar作為可滾動組件的任意一個父級組件即可,如:
Scrollbar 和 CupertinoScrollbar 都是通過監(jiān)聽滾動通知來確定滾動條位置的。關(guān)于的滾動通知的詳細內(nèi)容我們將在本章最后一節(jié)中專門介紹。
CupertinoScrollbar是 iOS 風(fēng)格的滾動條,如果你使用的是Scrollbar,那么在iOS平臺它會自動切換為CupertinoScrollbar
分享標(biāo)題:flutter滾動,flutter滾動文字
網(wǎng)頁路徑:http://fisionsoft.com.cn/article/phgejj.html