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初步实测,没有问题

GitHub地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值