此文章中,包括簡單的布局饥臂,九宮格布局和頭視圖的使用小demo
前言
在iOS開發(fā)中腊敲,用的最多的一個控件就是TableView,ListView和TableView實現(xiàn)的效果一下找爱,是React Native中的核心組件惯驼,高效的用于顯示一個可以垂直滾動變化的數(shù)據(jù)列表清蚀。
TableView的工作原理是:先加載UI,有數(shù)據(jù)源之后再刷新界面匕荸。
ListView的工作原理是:想創(chuàng)建一個ListView.DataSource數(shù)據(jù)源,然后給他傳遞一個普通的的數(shù)據(jù)組枷邪,在使用數(shù)據(jù)源來實例化一個ListView組件榛搔。使用renderRow回調(diào)函數(shù),接受數(shù)組中的每個數(shù)組作為參數(shù)东揣,返回一個可渲染的組件践惑。
一、ListView常用屬性
ListView ?繼承ScrollerView相關(guān)的樣式屬性
DataSource? ?數(shù)據(jù)屬性
initialListSize ?number?
?控制組件剛掛載的時候渲染多少行數(shù)據(jù)嘶卧,用來確保首屏顯示合適數(shù)量的數(shù)據(jù)尔觉,而不是花費太多幀逐步顯示出來。
onEndReachedThreshold ?number?
?設(shè)置什么時候偏移量達到設(shè)置的臨界值調(diào)用onEndReached
pageSize ?number ?
每幀渲染的行數(shù)
removeClippedSubviews? bool? ?
該屬性用于提供大數(shù)據(jù)列表的滾動性能芥吟。該使用的時候需要給每一行(row)的布局添加over:'hidden'樣式穷娱。該屬性默認(rèn)是開啟狀態(tài)。
scrollRenderAheadDistance ?number?
當(dāng)一行接近屏幕范圍多少像素之內(nèi)的時候运沦,開始渲染這一行。
IOS ? stickyHeaderIndices[number]
一個子視圖下標(biāo)的數(shù)組配深,用于決定哪些成員會在滾動之后固定在屏幕頂端携添。?
function屬性
onChangeVisibleRows? (visibleRows,changedRows)=>void??
?當(dāng)可見的行發(fā)生變化的時候回調(diào)該方法篓叶。?
onEndReached??
當(dāng)所有的數(shù)據(jù)都已經(jīng)渲染過烈掠,并且列表被滾動到距離最底部不足onEndReachedThreshold個像素的距離時調(diào)用原生的滾動事件會被作為參數(shù)傳遞。
注意:當(dāng)?shù)谝淮武秩緯r缸托,如果數(shù)據(jù)不足一屏(比如初始值是空的)左敌,這個事件也會被觸發(fā)。
renderFooter? ()=>renderable??
在每次渲染過程中頭和尾總會重新進行渲染俐镐。如果發(fā)現(xiàn)該重新繪制的性能開銷比較大的時候矫限,可以使用StaticContainer容器或者其他合適的組件。
renderHeader? 在每一次渲染過程中Footer(尾)該會一直在列表的底部佩抹,header(頭)該會一直在列表的頭部叼风,用法同上。
renderRow ??(rowData,sectionID,rowID,highlightRow)=>renderable
該方法有四個參數(shù)棍苹,其中分別為數(shù)據(jù)源中一條數(shù)據(jù)无宿,分組的ID,行的ID枢里,以及標(biāo)記是否是高亮選中的狀態(tài)信息孽鸡。
renderScrollComponent ? (props)=>renderable??
該方法可以返回一個可以滾動的組件蹂午。默認(rèn)該會返回一個ScrollView
renderSectionHeader??(sectionData,sectionID)=>renderable
如果設(shè)置了該方法,這樣會為每一個section渲染一個粘性的header視圖彬碱。該視圖粘性的效果是當(dāng)剛剛被渲染開始的時候膘流,該會處于對應(yīng)的內(nèi)容的頂部,然后開始滑動的時候操灿,該會跑到屏幕的頂端按脚。直到滑動到下一個section的header(頭)視圖,然后被替代為止皮迟。
renderSeparator ?(sectionID,rowID,adjacentRowHighlighted)=>renderable
如果設(shè)置該方法搬泥,會在被每一行的下面渲染一個組件作為分隔。除了每一個section分組的頭部視圖前面的最后一行伏尼。
方法
導(dǎo)出一些用于性能分析的數(shù)據(jù)忿檩。
scrollTo
滾動到指定的X,Y偏移處爆阶,可以指定是否加上過渡動畫燥透。
二、ListView高級特性
2.1給每段/組數(shù)據(jù)天天以后帶有粘性的頭部辨图。
2.2在列表頭部和尾部增加單獨的內(nèi)容班套,在到達列表尾部的時候調(diào)用函數(shù)(onEndReached),還有在視野可見的數(shù)據(jù)變化時調(diào)用回調(diào)函數(shù)(onChangeVisibleRows)故河。
2.3在性能方面優(yōu)化
只更新變化的行 - 提供給數(shù)據(jù)源的rowHasChanged函數(shù)可以告訴ListView中它是否需要重繪一行數(shù)據(jù)(即:數(shù)據(jù)是否發(fā)生了變化)參見ListViewDataSource
限制頻率的行渲染-默認(rèn)情況下吱韭,每次消息循環(huán)只有一行會被渲染(用可以pageSize屬性配置)這把較大的工作分散成小的碎片,以降低因為渲染而導(dǎo)致丟幀的可能性鱼的。
三理盆、ListView常用Demo
3.1簡單的電商demo
3.1.1listView的使用步驟:
代碼截圖:
運行效果:
這種比較簡單,只要到時候改變返回的row中的View的樣式即可
3.2九宮格demo
使用ListView實現(xiàn)九宮格的原理就是凑阶,一個listView,將cell通過flex布局實現(xiàn)猿规,主軸方向的改變,然后設(shè)置宙橱,每個cell的布局得到姨俩。
注意:在這個過程中,實現(xiàn)row主軸的改變后养匈,實現(xiàn)多行顯示總是不行哼勇,原因是removeClippedSubviews={false}的默認(rèn)狀態(tài)是ture是隱藏的。
3.2.1 代碼截圖:
運行截圖:
3.3分組帶有頭視圖的demo?
DataSource 的方法解析及技術(shù)分析
1.數(shù)組的提取和更新方法
clone方法會自動提取新數(shù)據(jù)并進行逐行對比(使用rowHasChanged方法中的策略)呕乎,這樣ListView就知道哪些行需要重新渲染了积担。
?cloneWithRows(dataBlob(原始數(shù)據(jù)), rowIdentities(二維數(shù)組))
cloneWithRowsAndSections(dataBlob(原始數(shù)據(jù)), sectionIdentities(數(shù)組,包含了section標(biāo)識符), rowIdentities(數(shù)組))
section標(biāo)題和行數(shù)據(jù)提供自定義的提取方法和hasChanged比對方法猬仁。如果不提供帝璧,則會使用默認(rèn)的defaultGetRowData和defaultGetSectionHeaderData方法來提取行數(shù)據(jù)和section標(biāo)題先誉。
默認(rèn)的提取函數(shù)處理一下的數(shù)據(jù)類型
{ sectionID_1: { rowID_1: rowData1, ... }, ... } ? ? =>>> ? key:{}
{ sectionID_1: [ rowData1, rowData2, ... ], ... }? ? =>>> ? key:[]
[ [ rowData1, rowData2, ... ], ... ] ? ? ? ? ? ? ? ? ?= >>>> [[],[]....]
通過構(gòu)造函數(shù)提取數(shù)組的方法一共有四種:
(1).getRowData(sectionIndex, rowIndex)? ? 返回渲染行數(shù)所需的數(shù)據(jù)(指定如何從原始dataBlob中提取數(shù)據(jù))。
(2).getSectionHeaderData(dataBlob, sectionID); 獲取section標(biāo)題數(shù)據(jù)的烁。
(3)rowHasChanged(prevRowData, nextRowData); ?通過對比創(chuàng)建數(shù)組
(4). sectionHeaderHasChanged(prevSectionData, nextSectionData); ?通過對比創(chuàng)建
2.其他方法
getRowCount() ?獲取行數(shù)
getRowAndSectionCount() ? 獲取原始數(shù)據(jù)的分組個數(shù)
rowShouldUpdate(sectionIndex, rowIndex) ??返回值表明某行數(shù)據(jù)是否已變更褐耳,需要重新渲染。
getRowData(sectionIndex, rowIndex) ??返回渲染行所需的數(shù)據(jù)(指定如何從原始dataBlob中提取數(shù)據(jù))渴庆。
getSectionIDForFlatIndex(index) ? ?給定索引值铃芦,求其對應(yīng)sectionID。如果查找不到則返回null襟雷。
getSectionLengths() ??返回一個數(shù)組刃滓,包含每個section的行數(shù)量。
sectionHeaderShouldUpdate(sectionIndex) ??返回值用于說明section標(biāo)題是否需要重新渲染耸弄。
看到上邊的大家可能還是蒙蒙的咧虎,簡單的說就說:
DataBlob就是原始數(shù)據(jù)就是一個大的字典{
sectionID1:{},或者[]
}
sectionIDs = ['sectionID1',sectionID2',sectionID3'.......] 每組的標(biāo)題
rowIDS = [[row1,row2],[row1,row2],[row1,row2],[row1,row2].....] ?每組的數(shù)據(jù)
第一步需要在datasource中,設(shè)置ListView獲取row和section方法
第二步因為需要對數(shù)據(jù)進行循環(huán)拆分计呈,組合成dataBlob需要的數(shù)據(jù)樣式屬于耗時操作砰诵,放到componentDidMount方法中,完成操作后刷新狀態(tài)捌显,將數(shù)據(jù)傳到listView的render()方法中茁彭。
第三步,返回相關(guān)函數(shù)扶歪,設(shè)置屬性樣式布局
代碼截圖
運行結(jié)果:
完整demo請https://github.com/nanaLxs/ListView-demo下載尉间。如果感覺可以請star。在這里謝謝啦;髯铩!