react native 索引列表、展示大量資料的索引列表、磁吸索引列表、快速載入大量資料的列表
阿新 • • 發佈:2019-02-07
近期,在完成一個含有索引列表功能的專案。效果如圖所示:
首先,我用的是react native 所提供的 ListView 這個元件(由於這個元件已經過期,而且此列表為分組列表,所以建議大家使用react native 官網所提供的 SectionList 元件,後面會有demo來講解如何使用),然後計算每個組的高度,然後存起來,在點選索引的時候,用 元件所提供的scrollTo 方法來進行滑動調相應的位置。我的具體實現為:
(1)用ListView元件,將列表展示出來
<ListView ref={listView => this._listView = listView} contentContainerStyle={styles.contentContainer} dataSource={this.state.dataSource} renderRow={this._renderListRow.bind(this)} renderSectionHeader={this._renderListSectionHeader.bind(this)} enableEmptySections={true} initialListSize={500}/>
(2) /*分組的組名*/
_renderListSectionHeader(sectionData, sectionID) {
組名的渲染,具體程式碼,在後面看後面提供的具體demo
}
(3)/*主體資料列表*/
_renderListRow(cityJson, rowId) {
每一行資料的渲染,這裡分為了關鍵字為字母和非字母兩種渲染格式。具體程式碼,看後面提供的具體demo
}
(4){/*索引*/} <View style={{ position: 'absolute', height: height, top: this.state.letterMarginTop, bottom: 0, right: this.state.letterMarginRight, backgroundColor: 'transparent', justifyContent: 'flex-start', alignItems: 'flex-end' // alignItems: 'center', //justifyContent: 'center' }}> 索引採用絕對定位的方式,將索引定位到右側。具體程式碼,看後面提供的具體demo </View>
最後實現的效果圖,如下:
具體的demo地址: https://github.com/LQ0611/IndexList.git
如果想看效果,請將本包引入你的專案中,並呼叫包中 test-MainPage 頁面;如果想實際使用,請看包中 readme 檔案。
在實際使用中,由於出入的資料在幾百個,資料量過大,而且由於要計算各個組的高度,所以這些資料必須第一次時就要全部渲染,所以這個元件在進入的時候,非常慢。因此,為了改善進入的體驗,而有了改進版,如下介紹。
(1)將資料展示出來
<LargeList style={{ width:width,height:height-70,}} // 樣式 ref={ref => (this._listView = ref)} //後面在滾動時,用它來做標識,明確操作的是哪一個 reloadData={this.state.contacts} //傳入的資料 numberOfSections={()=>this.state.contacts.length} //本資料中有多少個組 numberOfRowsInSection={section => this.state.contacts[section].info.length} //某一組中,有多少條資料 heightForCell={()=>this.state.heightForCell} //渲染每一條資料時,所佔的高是多少 heightForSection={()=>this.state.heightForSection} //渲染時,每個組名所佔的高是多少 renderSection={this.renderSection.bind(this)} //組名的渲染方法 renderCell={this._renderItem.bind(this)} //組內資料的渲染方法 renderFooter={this.renderFooter.bind(this)} //在滑動到列表底部時,在列表底部所顯示的提示內容 />
(2)滾動的計算與實現
首先,將我們資料中的header取出,並通過toUpperCase方法,轉換成大寫
然後,將取出的組名存放到一個數組中備用
在然後,根據統計出的每個組有多少條資料 * 設定好的資料的高度 + 多少個組* 每個組的高度,將計算得到的結果,儲存進資料,當點選某個索引是,就能直接得到要滾動 的距離
this.state.contacts.map(contacts => {
let key = contacts.header.toUpperCase();
if (dataBlob[key]) {
let subList = dataBlob[key];
subList.push(contacts);
} else {
let subList = [];
subList.push(contacts);
dataBlob[key] = subList;
}
});
let sectionIDs = Object.keys(dataBlob);
/*計算高度*/
let rowIDs = sectionIDs.map((sectionID,i) => {
let thisRow = [];
let count = this.state.contacts[i].info.length;
console.log("count:",count);
for (let ii = 0; ii < count; ii++) {
thisRow.push(ii);
}
let eachheight = this.state.heightForSection + this.state.heightForCell * thisRow.length;
//if (sectionID === key_hot || sectionID === key_now || sectionID === key_last_visit) {
totalheight.push(eachheight);
return thisRow;
});
滾動事件:
_scrollTo(index, letter) {
this.refs.toast.close();
let position = 0;
for (let i = 0; i < index; i++) {
position += totalheight[i]
}
console.log("position",position)
this._listView.scrollTo({x:0,y:position+5}) ; //滾動方法
this.refs.toast.show(letter, DURATION.LENGTH_SHORT); //在點選某個索引時 ,螢幕上回短暫的顯示此索引的字母
}
(3)索引的實現
{/*索引*/}
<ScrollView style={{
position: 'absolute',
height: this.state.letterHeight,
top: this.state.letterMarginTop,
bottom: 0,
right: this.state.letterMarginRight,
backgroundColor: 'transparent',
// alignItems: 'center',
//justifyContent: 'center'
}}>
索引也是採用絕對定位到右邊。詳情請看後面的具體的demo
</ScrollView>
(4)組名的展示方法
/*組名*/
renderSection(section){
具體的展示程式碼請看下面的demo
}
(5)組內資料的展示
/*主體資料展示*/
_renderItem (section: number, row: number){
具體的展示程式碼請看下面的demo
}
具體的demo地址:https://github.com/LQ0611/IndexList-v2.git
效果圖: