React Native中,ScrollView组件可以使用stickyHeaderIndices轻松实现sticky效果。

而使用ListView组件时,使用stickyHeaderIndices则不生效。

在IOS中的ListView的内部结构,实际是由多个Section组成,最典型的案例就是iphone手机的通讯录,滚动时每个section header会吸顶。

而在web端,使用position : -weblit-sticky实现的吸顶效果,也是类似的原理。具体可以看下之前的文章:《position:sticky 使用条件分析》.

好了,废话不多。在ListView中实现sticky,需要使用cloneWithRowsAndSections 方法,将dataBlob(object),sectionIDs (array),rowIDs (array) 三个值传进去即可。

dataBlob

dataBlob包含ListView所需的所有数据(section header 和 rows),在ListView渲染数据时,使用 getSectionDatagetRowData 来渲染每一行数据。dataBlobkey值包含sectionID + rowId

51

sectionIDs

sectionIDs 用于标识每组section。

52

rowIDs

53

rowIDs 用于描述每个section里的每行数据的位置及是否需要渲染。在ListView渲染时,会先遍历rowIDs获取到对应的dataBlob数据。

根据上面3个数据的定义,模拟出对应的数据结构如下:

var dataBlob = {
     'sectionID1' : { ...section1 data },
     'sectionID1:rowID1' : { ...row1 data },
     'sectionID1:rowID2' : { ..row2 data },
     'sectionID2' : { ...section2 data },
     'sectionID2:rowID1' : { ...row1 data },
     'sectionID2:rowID2' : { ..row2 data },
     ...
}

var sectionIDs = [ 'sectionID1', 'sectionID2', ... ]

var rowIDs = [ [ 'rowID1', 'rowID2' ], [ 'rowID1', 'rowID2' ], ... ]

DataSource中,告诉ListView获取row和section的方法。

var getSectionData = (dataBlob, sectionID) => {
      return dataBlob[sectionID];
 }
var getRowData = (dataBlob, sectionID, rowID) => {
      return dataBlob[sectionID + ':' + rowID];
}
this.ds = new ListView.DataSource({
      getSectionData: getSectionData,
      getRowData: getRowData,
      rowHasChanged: (r1, r2) => r1 !== r2,
      sectionHeaderHasChanged: (s1, s2) => s1 !== s2
})

最后将数据传进ListView

 this.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs) 

最终效果如图:

1

完整代码示例可查看:https://github.com/hugohua/rn-listview-example

 

参考文章:

http://moduscreate.com/react-native-listview-with-section-headers/

2 thoughts on “React Native ListView sticky效果实现

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required