react-native列表分组,侧边字母快速定位。
这个是仿照着写的大概的一个功能实现。颜色样式等都没有做处理。
逻辑是:进入到这个页面的时候把当前位置传到这个页面上来,展示一个列表和一列字母。选择新的城市后替换所在城市。
<View style={styles.view}>
<View style={styles.view2}>
<Header thisCity={this.state.thisCity} ref={'hotHeader'}/>
<SectionList
renderItem={({item, index, section}) => (
<TouchableNativeFeedback onPress={() => {
Alert.alert('确定选择' + item + '吗?',
'点击OK后会切换到' + item + '的商店',
[{
text: 'OK', onPress: () =>
this.setState({
thisCity: item,
RecentlyArr: item
})
}],
{cancelable: false})
}}>
<View style={styles.TouchableNativeFeedback}>
<Text style={{fontSize: 22}} key={index}>{item}</Text>
</View>
</TouchableNativeFeedback>
)}
renderSectionHeader={({section: {title}}) => (
<View style={styles.listTitle}>
<Text style={{fontSize: 20}}>{" " + title}</Text>
</View>
)}
sections={cityData}
keyExtractor={(item, index) => item + index}
ItemSeparatorComponent={ItemDivideComponent}
ref={'SectionList'}
ListHeaderComponent={SectionListHeadre}
getItemLayout={(data,index)=>({
length: 40, offset: 40 * index , index
//方法说明:
//当调用this.refs.SectionList.scrollToLocation这个方法的时候,列表的所有数据并没有渲染完成,这个时候跳到指定位置时,程序就无法确定。
//所有用此方法来规定位置以及数据,length:列表行高,offset是第几行,index:跳转到哪个index就是这个index
})}
/>
</View>
<TouchableOpacity style={styles.TouchableOpacity}
number={1}
>{textList}</TouchableOpacity>
</View>
Header头部 显示当前位置,有一个当前位置打属性。
SectionList就是可以分组的列表控件,他又几个属性和方法,
renderItem item的布局
renderSectionHeader 分组的布局,如图中分组头A/B/C
sections 数据源 ,我自己造的数据源,格式如下
[
{
"title": "A",
"data": [
"阿坝",
"阿拉善",
"阿里",
"安康",
"安庆",
"鞍山",
"安顺",
"安阳",
"澳门"
]
},
{
"title": "B",
keyExtractor key
ListHeaderComponent 列表的头,是整体列表的头,不是每一组的头。
getItemLayout 这个在官网上没有找到太多的资料,看注释。
ref={‘SectionList’} 定义这个ref是用作字母快速定位时可以用到。快速定位列表位置的时候,通过ref获取到SectionList对象,通过自身对象在操作列表定位到哪个位置
SectionListHeadre,热门城市。
render() {
let hotCityArr = ["北京", "上海", "深圳", "广州", "南京", "成都", "苏州", "杭州", "武汉"];
let textArr = [];
for (let i = 0; i < 9; i++) {
textArr.push(
<TouchableNativeFeedback key={i} onPress={() => {
Alert.alert('确定选择' + hotCityArr[i] + '吗?',
'点击OK后会切换到' + hotCityArr[i] + '的商店',
[
// 可以有三个按钮
// {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
// {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
{
text: 'OK', onPress: () =>
DeviceEventEmitter.emit("hotTitle", hotCityArr[i].toString())
},
],
{cancelable: false})
}}>
<Text key={i} style={{
width: width / 3 - 10,
height: 50,
backgroundColor: '#FFFFFF',
textAlign: 'center',
fontSize: 18,
paddingTop: 10,
}}>{hotCityArr[i]}</Text>
</TouchableNativeFeedback>
)
}
上边两处都有DeviceEventEmitter.emit(“hotTitle”, hotCityArr[i].toString())
DeviceEventEmitter可以完成发送消息和接收消息,而这个行就是发送消息,我发送了一个选中城市的消息,
componentDidMount() {
let self = this
this.listener = DeviceEventEmitter.addListener('hotTitle', function (hotTitle) {
self.setState({
thisCity: hotTitle,
})
});
}
在生命周期中接收了消息,改变状态。和android中java中相似度很多。所以没多纠结这个。这样就已经完成了列表。
<TouchableOpacity style={styles.TouchableOpacity}
number={1}
>{textList}</TouchableOpacity>
textList就是所有数据中的首字母控件的数组。
render() {
let textList = [];
for (let i = 0; i < cityData.length; i++) {
textList.push(
<TouchableOpacity key={i} onPressIn={({nativeEvent: e}) => this.touchEnd(e, i)}>
<Text style={{fontSize: 16}}>{cityData[i].title}</Text>
</TouchableOpacity>
)
}
}
touchEnd(e, index) {
this.refs.SectionList.scrollToLocation(
{
sectionIndex: index,
itemIndex: 0,
viewOffset: 25,
},
)
}
在这里获取了列表对象设置需要定位的索引,viewOffset是偏移量,
遇到错误(图在公司,忘了)
这个错误是这样的,列表A组在前Z组在最后,当我进入页面后直接点击字母Z快速定位的时候产生的,可想而知这很明显,那个时候Z组还没有绘制,发生了这个问题。就用到了刚才说的getItemLayout 这个方法。
以上由真机三星S8初步实测,没有问题