此控件的package我已經(jīng)托管到了 pub倉庫
十余年的縉云網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整縉云建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“縉云網(wǎng)站設(shè)計(jì)”,“縉云網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
如果你被墻住了,也可以看 國內(nèi)鏡像
使用方式就是在你的flutter pubspec.yaml中添加依賴:
然后flutter packages get更新依賴即可
最近寫demo時(shí)發(fā)現(xiàn)Flutter自帶的ListView widget很簡(jiǎn)陋,沒有分隔線,沒有section/row之分,也沒有sectionHeader,如果要實(shí)現(xiàn)一個(gè)有分割線,有section區(qū)分,有section header的ListView,耦合會(huì)非常嚴(yán)重:
在 上沒有找到封裝好的這種TableView,于是乎決定自己寫一個(gè),命名為SectionTableView
本人是iOS開發(fā),所以習(xí)慣了iOS上的UITableView的調(diào)用風(fēng)格,所以在實(shí)現(xiàn)flutter的SectionTableView時(shí),決定實(shí)現(xiàn)如下功能
為了實(shí)現(xiàn)這些功能,并且方便后期增加滾動(dòng)功能,上下拉刷新功能,使用了StatefulWidget作為父類:
接著在對(duì)應(yīng)的_SectionTableViewState中的build方法中,返回ListView:
熟悉flutter ListView的同學(xué)知道,ListView的builder類方法,有一個(gè)itemBuilder回調(diào)函數(shù),參數(shù)是當(dāng)前的上下文,和將要渲染的行索引index,index對(duì)應(yīng)想要獲取的某一行控件(cell或者叫ListItem),返回非空的組件就證明這個(gè)index有值,返回null就表示列表到盡頭了。
我們需要做的就是對(duì)index進(jìn)行映射,判斷當(dāng)前index對(duì)應(yīng)的控件,應(yīng)該是列表里的section header,還是分隔線devider,還是某一行的真正內(nèi)容cell。
出于性能的考慮,不可能每次調(diào)用 _buildCell的時(shí)候,都計(jì)算一遍index對(duì)應(yīng)的section和row的位置,所以定義了一個(gè)類成員變量indexPathSearch,是數(shù)組,數(shù)組長(zhǎng)度就是ListView所有的行,當(dāng) _buildCell 的參數(shù)index大于等于indexPathSearch的長(zhǎng)度的時(shí)候,就返回null,表示列表內(nèi)容到此為止了。
indexPathSearch里每一個(gè)元素,就是index對(duì)應(yīng)的section和row(稱為indexPath),index指向?qū)嶋H行(cell)的時(shí)候,section和row都是大于等于0的,當(dāng)section大于等于0,row==-1的時(shí)候,表示這里是一個(gè)section header,當(dāng)兩者都等于-1的時(shí)候,表示這里是一個(gè)分割線:
計(jì)算好了index到indexPath的映射,剩下的就好說了,在_buildCell中,提取indexPath并判斷indexPath的內(nèi)容,返回對(duì)應(yīng)的控件:
這是我的第一個(gè)flutter package,目前還很簡(jiǎn)陋,flutter目前尚且如此,所以大家一起改善它,
下一步將優(yōu)化如下內(nèi)容:
如果大家喜歡,請(qǐng)多多star我的 項(xiàng)目GitHub
其他語言像是js,提供的迭代器是可以直接獲取element,index的,但是用dart的map()發(fā)現(xiàn)無法獲取下標(biāo),實(shí)際上dart的迭代器只支持獲取element自身,想要獲得index,就需要借助asMap(),Dart提供的asMap()將列表轉(zhuǎn)換為Map。
Dart提供了List.generate方法獲取index
AzListView,F(xiàn)lutter 城市列表,聯(lián)系人列表,自定義Header,索引,懸停效果。
Set是不能重復(fù)的集合,所以可以用Set去重;
String、int、double類型示例,如下:
String類型:
int類型:
double類型:
可以看到, Set集合可直接對(duì)String、int、double類型去重 ;
Map、List、bool類型和String、int、double類型對(duì)比示例,如下:
可以看到,當(dāng)自定義對(duì)象實(shí)例化為同一個(gè)對(duì)象時(shí),Set會(huì)過濾掉同一個(gè)實(shí)例化的對(duì)象;當(dāng)自定義對(duì)象實(shí)例化為不同對(duì)象時(shí),Set不會(huì)去重,即使對(duì)象數(shù)據(jù)內(nèi)容一樣,這不符合我們的業(yè)務(wù);
可以看到,重寫自定義對(duì)象==方法,Set還是不能去重;
上面重寫自定義對(duì)象hashCode和==方法,以title不同區(qū)分不同對(duì)象;
可以看到,重寫自定義對(duì)象hashCode和==方法,Set集合對(duì)自定義對(duì)象去重才有效;并且Set集合里有相同對(duì)象時(shí)(相同對(duì)象為上面自定義對(duì)象title值相同的對(duì)象),后面相同的對(duì)象就不會(huì)被加入Set集合里了( 如上面title一樣,boolValue不一樣,這樣被認(rèn)為相同的對(duì)象,因?yàn)橹貙懽远x對(duì)象hashCode和==方法,以title不同區(qū)分不同對(duì)象;Set集合里最開始加入的TestModel('a', boolValue: false),數(shù)據(jù)不會(huì)被相同對(duì)象TestModel('a', boolValue: true)覆蓋 )。
網(wǎng)上介紹flutter Set集合時(shí)一般會(huì)介紹Set沒有順序,這點(diǎn)不太理解,可能是不能通過索引來獲取對(duì)應(yīng)的值吧,像Java語言的Set集合確實(shí)是無序的,但flutter的Set集合保持著子元素的有序性。 如下:
可以看到,將Set通過toList()方法轉(zhuǎn)為L(zhǎng)ist后,List里子元素的順序和子元素插入Set集合的順序是一致;對(duì)于自定義對(duì)象亦是如此,可自行驗(yàn)證。
為什么Set集合會(huì)保持子元素插入順序呢
我們看下Set源碼,如下:
從源碼我們可知,Set()是一個(gè)工廠構(gòu)造方法,根據(jù)工廠構(gòu)造方法的特點(diǎn),Set是由LinkedHashSet實(shí)例化的。
從上面注釋可知,HashSet是無序的,LinkedHashSet保持著子元素插入的順序。而Set是由LinkedHashSet實(shí)例化的,所以Set保持著子元素插入的順序。
如想要深入分析LinkedHashSet,LinkedHashSet源碼中有很多external聲明的方法,可參考 如何找到flutter external聲明方法的實(shí)現(xiàn)
demo傳送門
最近一個(gè)項(xiàng)目要實(shí)現(xiàn)可以無限循環(huán)的PageView,主要思路是在初始化pageview的list的時(shí)候在開始和結(jié)尾多加一個(gè)結(jié)尾和開頭的widget,當(dāng)滑動(dòng)到開頭和結(jié)尾的時(shí)候手動(dòng)進(jìn)行頁面的切換,詳細(xì)可以搜索pageview無限輪播。
這種方法有一個(gè)要點(diǎn)就是要維護(hù)兩個(gè)索引,一個(gè)是內(nèi)部list的索引,一個(gè)是外部顯示的索引,由于list的容量是比顯示的數(shù)量多2的,所以如果要在外部進(jìn)行一些比如指示器或者計(jì)時(shí)器功能要進(jìn)行和頁面同步顯示或者切換頁面操作時(shí),需要將顯示的索引轉(zhuǎn)換成list的索引。
不過網(wǎng)上說的都是一些比較簡(jiǎn)單的實(shí)現(xiàn),看到比較多的就是當(dāng)滑動(dòng)到要手動(dòng)切換的時(shí)候進(jìn)行一個(gè)時(shí)延,這樣可以避免直接切換頁面造成的卡頓和跳動(dòng)現(xiàn)象。但是存在一個(gè)問題,如果要同時(shí)實(shí)現(xiàn)一個(gè)跟隨頁面切換的指示器,就會(huì)出現(xiàn)當(dāng)頁面切換過去之后指示器才會(huì)跟著過去,因?yàn)轫撁媲袚Q的時(shí)候執(zhí)行了時(shí)延,而時(shí)延之后才會(huì)真正改變索引,此時(shí)才會(huì)setstate,之后指示器才能響應(yīng)到索引的切換,但是如果在時(shí)延之前就切換的話又會(huì)出現(xiàn)指示器先行的情況。因此這種方法其實(shí)是存在一些問題的。
所以解決這個(gè)問題的關(guān)鍵在于如何進(jìn)行頁面切換的判斷。這里可以有兩種思路實(shí)現(xiàn),第一種是實(shí)現(xiàn)viewpage的onpagechanged方法,在里面進(jìn)行邏輯的判斷,然后用controller來進(jìn)行頁面跳轉(zhuǎn),不過這種方法存在當(dāng)controller跳轉(zhuǎn)的時(shí)候又會(huì)回調(diào)onpagechanged,所以就會(huì)出現(xiàn)多次對(duì)索引不必要操作,而且如果有比如計(jì)時(shí)器等額外的功能的話可能不方便將頁面邏輯分開,而且依舊無法解決指示器延遲問題,同時(shí)也很難進(jìn)行細(xì)粒度的操作。
第二種方法我們就要去看pageview的源碼了,從源碼的角度來解決問題才是正確的方法。首先我們點(diǎn)進(jìn)去pageview的源碼
看到這里其實(shí)已經(jīng)有一些思路了,我們之前難點(diǎn)在于重寫了onpagechanged方法導(dǎo)致問題無法很好的解決,現(xiàn)在我們找到了onpagechanged調(diào)用的地方,只要找辦法避免掉就可以實(shí)現(xiàn)了。
當(dāng)然這里我們要說到NotificationListener,以及flutter對(duì)應(yīng)的冒泡事件傳輸機(jī)制,這里大家可以去看看這篇 文章 。
我來總結(jié)一下,其實(shí)就是flutter對(duì)于notification這個(gè)組件,有一中事件規(guī)則叫冒泡傳遞,底層的notification如果在它的 onNotification寫的邏輯中返回是false以及它不是根結(jié)點(diǎn),就會(huì)去向上遍歷尋找它的祖先notification組件,知道遇到root節(jié)點(diǎn)或者某一個(gè)返回true,則事件傳遞結(jié)束。
而且在onNotification中可以對(duì)多種事件進(jìn)行監(jiān)聽和處理,所以我們可以把對(duì)viewpage頁面跳轉(zhuǎn)對(duì)索引處理的邏輯寫在這里,而且我們可以分別處理比如滑動(dòng)開始的start事件和結(jié)束的end事件,分別進(jìn)行細(xì)粒度的邏輯的處理,這樣就可以在外部進(jìn)行操作和別的功能實(shí)現(xiàn)了。
因此不僅無限輪播事件可以通過這種方法來解決,如果有其他的操作也可以這樣進(jìn)行處理,而且因?yàn)槲覀儧]有傳入onpagechanged方法,所以不存在多次調(diào)用的問題,pageview那里判斷onpagechanged是null方法就不會(huì)進(jìn)去了,會(huì)直接我們寫在pageview外面的notification的邏輯。
最后的結(jié)構(gòu)大概這樣
分享名稱:flutter索引列表,Flutter 圖表
當(dāng)前網(wǎng)址:http://m.rwnh.cn/article6/phjeig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、、企業(yè)網(wǎng)站制作、做網(wǎng)站、網(wǎng)站制作、網(wǎng)站設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)