react native 索引列表、展示大量数据的索引列表、磁吸索引列表、快速加载大量数据的列表

近期,在完成一个含有索引列表功能的项目。效果如图所示:

首先,我用的是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 文件。

 

在实际使用中,由于出入的数据在几百个,数据量过大,而且由于要计算各个组的高度,所以这些数据必须第一次时就要全部渲染,所以这个组件在进入的时候,非常慢。因此,为了改善进入的体验,而有了改进版,如下介绍。

在改进版中,我们使用的组件是:LargeList  ,关于这个组件的出处,有兴趣的可以看一下  https://bolan9999.github.io/react-native-largelist/

(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

效果图:

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值