真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

UI系列中Android多子view嵌套通用的解決方案

這篇文章將為大家詳細講解有關UI系列中Android多子view嵌套通用的解決方案,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

創(chuàng)新互聯(lián)長期為近1000家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網生態(tài)環(huán)境。為江州企業(yè)提供專業(yè)的網站設計制作、成都網站建設,江州網站改版等技術服務。擁有10多年豐富建站經驗和眾多成功案例,為您定制開發(fā)。

1. 多子view嵌套應用背景

百度App在17年的版本中實現2個子view嵌套滾動,用于Feed落地頁(webview呈現文章詳情 + recycle呈現Native評論)。原理是在外層提供一個UI容器(我們稱之為”聯(lián)動容器”)處理WebView和Recyclerview連貫嵌套滾動。

當時的聯(lián)動容器對子view限制比較大,僅支持WebView和Recyclerview進行聯(lián)動滾動,數量也只支持2個子View。

隨著組件化進程的推進,為方便各業(yè)務解耦,對聯(lián)動容器提出了更高的要求,需要支持任意類型、任意數量的子view進行聯(lián)動滾動,也就是本文要闡述的多子view嵌套滾動通用解決方案。

先直觀感受下聯(lián)動容器嵌套滾動的Demo效果:

UI系列中Android多子view嵌套通用的解決方案

2. 多子view嵌套實現原理

同大多數自定義控件類似,聯(lián)動容器也需要處理子view的測量、布局以及手勢處理。測量和布局對聯(lián)動容器的場景來說非常簡單,手勢處理相對復雜些。

從demo效果可以看出,聯(lián)動容器需要處理好和子view嵌套滑動問題。嵌套滑動的處理方案有兩種

  1. 基于Google的NestedScrolling機制實現嵌套滑動;

  2. 是由聯(lián)動容器內部處理和子view嵌套滑動的邏輯。

百度App早期版本的聯(lián)動容器采用的方案2實現的,下圖為方案2聯(lián)動容器手勢處理流程:

UI系列中Android多子view嵌套通用的解決方案

筆者對方案2聯(lián)動容器的實現代碼做了開源,感興趣的同學可以參考:https://github.com/baiduapp-tec/LinkageScrollLayout。
基于google的NestedScrolling實現多子view嵌套能節(jié)省不少開發(fā)量,故筆者對多子view嵌套的實現采用方案一。

3. 核心邏輯

3.1 Google嵌套滑動機制

Google在Android 5.0推出了一套NestedScrolling機制,這套機制滾動打破了對之前Android傳統(tǒng)的事件處理的認知,是按照逆向事件傳遞機制來處理嵌套滾動,事件傳遞可參考下圖:

UI系列中Android多子view嵌套通用的解決方案

網上有很多關于NestedScrolling的文章,如果沒接觸過NestedScrolling的同學可參考下張鴻洋的這篇文章:https://blog.csdn.net/lmj623565791/article/details/52204039

3.2 接口設計

為了保證聯(lián)動容器中子view的任意性,聯(lián)動容器需提供完善的接口抽象供子view去實現。下圖為聯(lián)動容器暴露的接口類圖:

UI系列中Android多子view嵌套通用的解決方案

ILinkageScroll是置于聯(lián)動容器中的子view必須要實現的接口,聯(lián)動容器在初始化時如果發(fā)現某個子view沒實現該接口,會拋出異常。

ILinkageScroll中又會涉及兩個接口:LinkageScrollHandler、ChildLinkageEvent。

LinkageScrollHandler接口中的方法聯(lián)動容器會在需要時主動調用,以通知子view完成一些功能,比如:獲取子view是否可滾動,獲取子view滾動條相關數據等。

ChildLinkageEvent接口定義了子view的一些事件信息,比如子view的內容滾動到頂部或底部。當發(fā)生這些事件后,子view主動調用對應方法,這樣聯(lián)動容器收到子view一些事件后會做出相應的反應,保證正常的聯(lián)動效果。

上面僅簡單說明了下接口功能,想更加深入了解的同學請參考:https://github.com/baiduapp-tec/ELinkageScroll

接下來我們詳細分析下聯(lián)動容器對手勢處理細節(jié),根據手勢類型,將嵌套滑動分為兩種情況來分析:1. scroll手勢;2. fling手勢;

3.3 scroll手勢

先給出scroll手勢處理的核心代碼:

UI系列中Android多子view嵌套通用的解決方案

onNestedPreScroll()回調是google嵌套滑動機制NestedScrollingParent接口中的方法。當子view滾動時,會先通過此方法詢問父view是否消費這段滾動距離,父view根據自身情況決定是否消費以及消費多少,并將消費的距離放入數組consumed中,子view再根據數組中的內容決定自己的滾動距離。

代碼注釋比較詳細,這里整體再做個解釋:通過對子view的上邊沿閾值和聯(lián)動容器的scrollY進行比較,處理了3種case下的滾動情況。

第10行,當scrollY == topEdge時,只要子view沒有滾動到頂或者底,都由子view正常消費滾動距離,否則由聯(lián)動容器消費滾動距離,并將消費的距離通過consumed變量通知子view,子view會根據consumed變量中的內容決定自己的滑動距離。

第17行,當scrollY > topEdge時,也就是說當觸摸的子view頭部已經滑出聯(lián)動容器,此時如果手指向上滑動,滑動距離全部由聯(lián)動容器消費,如果手指向下滑動,聯(lián)動容器會先消費部分距離,當聯(lián)動容器的scrollY達到topEdge后,剩余的滑動距離由子view繼續(xù)消費。

第32行,當scrollY < topEdge這個和上一個第17行判斷類似,這里不做過多解釋。scroll手勢處理流程圖如下:

UI系列中Android多子view嵌套通用的解決方案

3.4 fling手勢

聯(lián)動容器對fling手勢的處理大致思路如下:如果聯(lián)動容器的scrollY等于子view的top坐標,則由子view自身處理fling手勢,否則由聯(lián)動容器處理fling手勢。

而且在一次完整的fling周期中,聯(lián)動容器和各子view將會交替去完成滑動行為,直到速度降為0,聯(lián)動容器需要處理好交替滑動時的速度銜接,保證整個fling的流暢行。接下來看下詳細實現:

UI系列中Android多子view嵌套通用的解決方案

onNestedPreFling()回調是google嵌套滑動機制NestedScrollingParent接口中的方法。當子view發(fā)生fling行為時,會先通過此方法詢問父view是否要消費這次fling手勢,如果返回true,表示父view要消費這次fling手勢,反之不消費。

第6行根據velocityY正負值記錄本次的fling的方向;

第7行,當聯(lián)動容器scrollY值等于觸摸子view的top值,fling手勢由子view處理,同時聯(lián)動容器對本次fling手勢的速度進行追蹤,目的是當子view內容滾到頂或者底時,能夠獲得剩余速度以讓聯(lián)動容器繼續(xù)fling;

第12行,由聯(lián)動容器消費本次fling手勢。下面看下聯(lián)動容器和子view交替fling的細節(jié):

UI系列中Android多子view嵌套通用的解決方案

fling的速度傳遞分為:

  1. 從聯(lián)動容器向子view傳遞;2. 從子view向聯(lián)動容器傳遞。

先看速度從聯(lián)動容器向子view傳遞。核心代碼在computeScroll()回調方法中。第9行,獲取聯(lián)動容器下一個滾動邊界值,如果達到下一個滾動邊界值,聯(lián)動容器需要將剩余速度傳給下個子view,讓其繼續(xù)滾動。

第46行,getNextEdge()方法內部整體邏輯:遍歷所有子view,將聯(lián)動容器當前的scrollY與子view的top/bottom進行比較來獲取下一個滑動邊界。

第34行,當聯(lián)動容器檢測到滑動到下個邊界時,則調用ILinkageScroll.flingContent()讓子view根據剩余速度繼續(xù)滾動。

再看速度從子view向聯(lián)動容器傳遞,核心代碼在第76行。當子view內容滾動到頂或者底,會回調onContentScrollToTop()方法或者onContentScrollToBottom()方法,聯(lián)動容器收到回調后,在第86行和第98行,繼續(xù)執(zhí)行后續(xù)滾動。fling手勢處理流程圖如下:

UI系列中Android多子view嵌套通用的解決方案

4. 滾動條

4.1 Android系統(tǒng)的ScrollBar

對于內容可滾動的頁面,ScrollBar則是一個不可或缺的UI組件,所以,ScrollBar也是聯(lián)動容器必須要實現的功能。

好在Android系統(tǒng)對滾動條的抽象非常友好,自定義控件只需要重寫View中的幾個方法,Android系統(tǒng)就能幫助你正確繪制出滾動條。我們先看下View中的相關方法:

UI系列中Android多子view嵌套通用的解決方案

對于垂直Scrollbar,我們只需要重寫computeVerticalScrollOffset(),computeVerticalScrollExtent(),computeVerticalScrollRange()這三個方法即可。Android對這三個方法注釋已經非常詳細了,這里再簡單解釋下:

computeVerticalScrollOffset()表示當前頁面內容滾動的偏移值,這個值是用來控制Scrollbar的位置。缺省值為當前頁面Y方向上的滾動值。

computeVerticalScrollExtent()表示滾動條的范圍,也就是滾動條在垂直方向上所能觸及的最大界限,這個值也會被系統(tǒng)用來計算滾動條的長度。缺省值是View的實際高度。

computeVerticalScrollRange()表示整個頁面內容可滾動的數值范圍,缺省值為View的實際高度。

需要注意的是:offset,extent,range三個值在單位上必須保持一致。

4.2 聯(lián)動容器實現ScrollBar

聯(lián)動容器是由系統(tǒng)中可滾動的子view組成的,這些子view(ListView、RecyclerView、WebView)肯定都實現了ScrollBar功能,那么聯(lián)動容器實現ScrollBar就非常簡單了,聯(lián)動容器只需拿到所有子view的offset,extent,range值,然后再根據聯(lián)動容器的滑動邏輯把所有子view的這些值轉換成聯(lián)動容器對應的offset,extent,range即可。接口設計如下:

UI系列中Android多子view嵌套通用的解決方案

LinkageScrollHandler接口在3.2小節(jié)解釋過,這里不在贅述。這里面三個方法由子view去實現,聯(lián)動容器會通過這三個方法獲取子view與滾動條相關的值。下面看下聯(lián)動容器中關于ScrollBar的詳細邏輯:

UI系列中Android多子view嵌套通用的解決方案

以上就是聯(lián)動容器實現ScrollBar的核心代碼,注釋也非常詳細,這里再重點強調幾點:

系統(tǒng)為了提高效率,ViewGroup默認不調用onDraw()方法,這樣就不會走ScrollBar的繪制邏輯。所以在第6行,需要調用setWillNotDraw(false)打開ViewGroup繪制流程;

第16行,收到子view的滾動回調,調用awakenScrollBars()觸發(fā)滾動條的繪制;

對于extent,直接使用缺省的extent,即聯(lián)動容器的高度;

對于range,對所有子view的range進行求和,最后得到值即為聯(lián)動容器的range;

對于offset,同樣先對所有子view的offset進行求和,之后還需要加上聯(lián)動容器自身的scrollY值,最終得到的值即為聯(lián)動容器的offset。

大家可以返回到文章開頭,再看下Demo中滾動條的效果,相比于市面上其它使用類似聯(lián)動技術的App,本文對滾動條的實現非常接近原生了。

5. 注意事項

聯(lián)動容器執(zhí)行fling操作時,借助OverScroller工具類完成的。代碼如下:

UI系列中Android多子view嵌套通用的解決方案

借助OverScroller.fling()方法完成聯(lián)動容器的fling行為,這段代碼在小米手機上運行聯(lián)動會出現問題,mScroller.getCurrVelocity()一直是0。

原因是小米手機Rom重寫了OverScroller,當fling()方法第三個參數傳0時,OverScroller.mCurrVelocity一直為NaN,導致無法計算出正確剩余速度。

為了解決小米手機的問題,我們需要將第三個參數傳個非0值,這里給1即可。

UI系列中Android多子view嵌套通用的解決方案

多子view嵌套實現原理并不復雜,對手勢處理的邊界條件比較瑣碎,需要來回調試完善。

關于UI系列中Android多子view嵌套通用的解決方案就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


網站題目:UI系列中Android多子view嵌套通用的解決方案
URL地址:http://weahome.cn/article/ihohes.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部