【Flutter】自定義ListView開發記錄(一)——設計滑動效果的處理方式
theme: condensed-night-purple
「這是我參與11月更文挑戰的第8天,活動詳情檢視:2021最後一次更文挑戰」。
前言
隨著熊孩子拆元件之ListView系列的結束,裝元件系列迎來了開始,從這篇開始我會記錄實現自定義ListView過程中,自己的思考和實現方式;也方便以後整理程式碼~
那麼首先從控制滑動方式這部分開始:
方案選擇——滑動效果控制
首先看看需要的滑動效果:
- 模擬翻頁
在這個模式下,不需要任何滑動效果;唯一所做的事便是將item從上往下依次羅列;
- 覆蓋翻頁
覆蓋翻頁模式下,在上面模擬翻頁效果基礎上,僅僅將滑動效果應用於當前最頂層的可見頁;
- 滾動翻頁
滾動翻頁效果跟ListView本身的效果沒什麼區別;
總結一下:
- 在第一個模式下,position 的改變,僅僅是在一頁翻過去的時候觸發;
- 在第二個模式下,position 的改變等同於現在的ListView,但是隻應用於第一個可見頁;
- 在第三個模式下,等同於ListView,不需要任何處理;
現在具體分析設計一下:
在上一篇文章中,對於滑動效果的控制,我設想提出了三種實現方式:
- 自定義ScrollerController;
- 自定義ViewPort;
- 自定義SliverList;
在ListView中,ScrollController 負責的部分就是控制ScrollPosition;ViewPort負責處理展示區域;SliverLit負責載入繪製內容,這三者之間是一個上級呼叫下級的關係;
雖說上級能呼叫下級,但是這三者其實並沒有什麼關聯,比如說ScrollController只關心自己的Positiion,SliverList展示的什麼,內容這麼樣並不關心,換句話說,ScrollController不知道SliverList的展示細節,除非它提供到ScrollPosition中;
這樣的話,ScrollController是無法得知SliverList的展示狀態;ViewPort也同理,僅僅通過position的修改,是無法區分當前position是在第幾頁,偏移量多少,讓position中的pixels生效有意義的地方,就是SliverList;
所以修改方式,應該是自定義SliverList;
具體實現方式:
這裡就參考之前的中秋投稿,說白了,對SliverList的RenderObject層進行修改:
在中秋投稿那次,我重寫了RenderSliverList 的 paint方法,在原本的SliverList中,是這麼規定繪製child的:
可以看到,其實paint方法中才是真正去計算 child 位置的地方,先看childMainAxisPosition方法:
在這裡會去計算主軸的位置,依據便是之前在layout方法中,遍歷child並給其parentData設定的layoutOffset引數,並減去當前已經滑動的距離;
交叉軸這塊,則直接返回0
自此就算出了具體的相對位置,之後就傳給paint方法進行繪製;
之後就是獲取下一個child,再次迴圈上述流程;
而如果要實現上面提到的效果,要做的事也比較簡單:
- 如果是效果1,那麼一直將所有child的繪製位置改為0即可;
- 如果是效果2,那麼僅僅在第一個child上加上scrollOffset的偏移量計算即可;
當然,由於繪製順序的關係,獲取child要先從lastChild獲取,並不斷取之前的child,直到第一個child;
如果再結合自定義路徑,加入變化Item的能力,那就要引入設想的LayoutManager的能力;
在此先將這部分邏輯抽離,等LayoutManager呼叫使用;
結語:
這個滑動效果實現方式非常簡單,麻煩的地方反而是如何將自定義SliverList的接進去~
下一步看下對Element層面的改造,暴露RenderObject 的layout、paint方法出去
- 【Flutter】小說閱讀器改版 —— 翻頁動畫(三)
- 【Flutter】小說閱讀器改版 (六)—— 在動畫播放中攔截手勢
- 【Flutter】小說閱讀器改版 (五)—— 整合ScrollActivity
- 【Flutter】小說閱讀器改版 (四)—— 讓ScrollActivity追蹤手勢最新位置
- 【Flutter】小說閱讀器改版 (三)—— 實現支援 Drag 的ScrollActivity
- 【Flutter】小說閱讀器改版 (二)—— 改進一下模擬翻頁的效果
- 【Flutter】小說閱讀器改版 (一)—— 模擬翻頁的思路優化
- 【Flutter】自定義ListView開發記錄(五)—— 提供手勢等資訊
- 【Flutter】自定義ListView開發記錄(四)—— 關於ParentData的設想和分析與簡單實踐
- 【Flutter】自定義ListView開發記錄(三)—— 處理HitTest手勢事件
- 【Flutter】自定義ListView開發記錄(二)——設計LayoutManager
- 【Flutter】自定義ListView開發記錄(一)——設計滑動效果的處理方式
- 【Flutter】熊孩子拆元件系列之拆ListView(十)—— 按自己的方式組裝修改ListView
- 【Flutter】熊孩子拆元件系列之拆ListView(九)—— AutomaticKeepAlive和KeepAlive
- 【Flutter】熊孩子拆元件系列之拆ListView(八)—— SliverList的運作機制
- 【Flutter】熊孩子拆元件系列之拆ListView(七)—— SliverList的基礎結構
- 【Flutter】熊孩子拆元件系列之拆ListView(六)—— SliverPadding
- 【Flutter】熊孩子拆元件系列之拆ListView(五)—— ViewPort
- 【Flutter】熊孩子拆元件系列之拆ListView(四)—— _ScrollableScope
- 【Flutter】熊孩子拆元件系列之拆ListView(三)—— GlowingOverscrollIndicator