1. 界面
用SectionList
把数据渲染出来
右边的A-Z
用Text
组件即可,这里为了做滑动定位,没有选择Touchable
组件
import * as React from 'react';
import {
Text,
View,
StyleSheet,
SectionList,
SafeAreaView,
} from 'react-native';
import countries from './countryCode.json';
const sectionMapArr = [
['A', 0],
['B', 1],
['C', 2],
['D', 3],
['E', 4],
['F', 5],
['G', 6],
['H', 7],
['I', 8],
['J', 9],
['K', 10],
['L', 11],
['M', 12],
['N', 13],
['O', 14],
['P', 15],
['Q', 16],
['R', 17],
['S', 18],
['T', 19],
['U', 20],
['V', 21],
['W', 22],
['X', 23],
['Y', 24],
['Z', 25],
];
export default class App extends React.Component {
render() {
return (
<SafeAreaView style={styles.container}>
<SectionList
containerStyle={{ flex: 1, justifyContent: 'center' }}
ItemSeparatorComponent={() => (<View style={{ borderBottomColor: '#F8F8F8', borderBottomWidth: 1, }} />)}
renderItem={({ item, index, section }) => (
<View style={styles.itemContainer}>
<Text style={styles.itemText} key={index}>
{item.countryName}
</Text>
</View>
)}
renderSectionHeader={({ section: { key } }) => (
<View style={styles.headerContainer}>
<Text style={styles.headerText}>{key}</Text>
</View>
)}
sections={countries}
keyExtractor={(item, index) => item + index}
/>
<View
style={{ width: 16, justifyContent: 'center' }}
>
{sectionMapArr.map((item, index) => {
return (
<Text
key={index}
>
{item[0]}
</Text>
);
})}
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFFFFF',
flexDirection: 'row',
},
headerContainer: {
padding: 5,
backgroundColor: '#F8F8F8',
},
headerText: {
fontWeight: 'bold',
},
itemContainer: {
paddingHorizontal: 5,
paddingVertical: 10,
},
itemText: {
fontSize: 16,
},
});
这时候界面已经完成了,然后就是增加触摸滑动定位的功能了。
给右侧的View
上启用手势
<View
style={{ width: 16, justifyContent: 'center' }}
onStartShouldSetResponder={() => true}
onMoveShouldSetResponder={() => true}
>
{sectionMapArr.map((item, index) => {
return (
<Text
key={index}
>
{item[0]}
</Text>
);
})}
</View>
这样我们就可以在触摸滑动的时候,获得滑动到的位置
3. 使用onLayout找到每个字母对应的X、Y
首先在constructor里声明一个实例属性,用来记录每个字母的信息:
this.ps = [];
然后在Text
组件上利用onLayout
获得每个字母的位置,并且存到this.ps
里:
<Text
key={index}
onLayout={({
nativeEvent: {
layout: { x, y, width, height },
},
}) => {
this.ps = this.ps.filter(i => i.key !== item[0]);
this.ps.push({
key: item[0], // 对应的字母 A-Z
min: y, // 字母顶部Y坐标
max: y + height, // 字母底部Y坐标
index: item[1], // 字母对应SectionList的index
});
}}
>
{item[0]}
</Text>
4. 根据滑动找到滑到哪个字母上
<View
style={{ width: 16, justifyContent: 'center' }}
onStartShouldSetResponder={() => true}
onMoveShouldSetResponder={() => true}
onResponderMove={({ nativeEvent: { pageY } }) => {
const offsetY = pageY - this.offsetY;
const find = this.ps.find(
i => i.min < offsetY && i.max > offsetY
);
if (find) {
console.log(find) // 滑动到的字母
}
}}
>
5. 根据触摸的字母,SectionList跳到对应的位置
- 先在constructor里创建ref
this.sectionlist = React.createRef();
- 在SectionList上绑定ref
ref={this.sectionlist}
- 调用SectionList的scrollToLocation
onResponderMove={({ nativeEvent: { pageY } }) => {
const offsetY = pageY - this.offsetY;
const find = this.ps.find(
i => i.min < offsetY && i.max > offsetY
);
if (find) {
this.sectionlist.current.scrollToLocation({
sectionIndex: find.index,
itemIndex: 0,
animated: false,
});
}
}}
完工