美文网首页
RN SectionList通讯录定位筛选

RN SectionList通讯录定位筛选

作者: liluo风 | 来源:发表于2020-07-12 11:10 被阅读0次

    需求:

    类似通讯录的右侧A-Z或者其他的筛选文案,点击或者滑动到某个文案的时候,弹出toast,并通知列表

    注意:由于我数据有限,所以使用的是 sectionList进行分组展示的,各位同学 可以根据自身需求 自行看合适使用什么样的列表,这个随意

    image.png
    1、创建toast弹框工具类
    自己随便写啦,加个定时器 神马的,确保能及时消失、显示 就OK了,我就不展示了
    
    2、创建定位筛选工具类
    import React, {Component} from 'react';
    import {StyleSheet, View, PanResponder,Text} from 'react-native';
    import PropTypes from 'prop-types';
    import px2dp from '../../utils/px2dp';
    export default class Filter extends Component {
      constructor(props) {
        super(props);
        this.tabItemHeight = []; //每个字母索引的高度
        this.locationTopHeight = -1;
        this.curIndex = 0;
      }
      componentWillMount() {
        this._panResponder = PanResponder.create({
          // 要求成为响应者:
          onStartShouldSetPanResponder: (evt, gestureState) => true,
          onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
          onMoveShouldSetPanResponder: (evt, gestureState) => true,
          onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
          onPanResponderGrant: (evt, gestureState) => {
            const {y0} = gestureState;
            this.setIndex(y0);
          },
          onPanResponderMove: (evt, gestureState) => {
            const {moveY} = gestureState;
            this.setIndex(moveY);
          },
          onPanResponderTerminationRequest: (evt, gestureState) => true,
          onPanResponderRelease: (evt, gestureState) => {
            const {data = [], selectToIndex} = this.props;
            data &&
              data.length > this.curIndex &&
              selectToIndex &&
              selectToIndex(this.curIndex);
          },
          onPanResponderTerminate: (evt, gestureState) => {
            // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
          },
          onShouldBlockNativeResponder: (evt, gestureState) => {
            // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
            // 默认返回true。目前暂时只支持android。
            return true;
          },
        });
      }
      //设置滚动的Index
      setIndex(y) {
        const {data = [], showToast, toastStyle, toastTextStyle} = this.props;
        let allHeight = this.locationTopHeight;
        for (let i = 0; i < this.tabItemHeight.length; i++) {
          allHeight = allHeight + this.tabItemHeight[i];
          if (y <= allHeight) {
            if (showToast) {
              showToast({
                text: data[i],
                toastStyle: [styles.toastStyle, toastStyle],
                titleStyle: toastTextStyle,
              });
            }
            this.curIndex = i;
            break;
          }
        }
      }
    
    showToast(obj = {}) {
       // DeviceEventEmitter.emit("showToast", obj);
      //  调用你的展示 toast 的方法,实在不行,原生 toast 也OK了
    }
      renderLocationView() {
        const {data = [], textStyle} = this.props;
        const list = data.map((item, index) => {
          return (
            <View
              key={index}
              onLayout={({nativeEvent: e}) => {
                this.tabItemHeight[index] = e.layout.height;
              }}>
              <Text style={[styles.locationItemStyle, textStyle]}>{item}</Text>
            </View>
          );
        });
        return list;
      }
      render() {
        const {allStyle, contentStyle} = this.props;
        return (
          <View style={[styles.locationView, allStyle]}>
            <View
              style={[styles.locationContentView, contentStyle]}
              {...this._panResponder.panHandlers}
              onLayout={({nativeEvent: e}) => {
                this.locationTopHeight = e.layout.y;
              }}>
              {this.renderLocationView()}
            </View>
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      locationView: {
        position: 'absolute',
        right: 0,
        top: 0,
        justifyContent: 'center',
        height: '100%',
      },
      locationContentView: {
        width: '100%',
        paddingRight: px2dp(24),
        paddingLeft: px2dp(24),
      },
      locationItemStyle: {
        color: '#999999',
        fontFamily: 'PingFangSC-Regular',
        fontSize: px2dp(24),
        lineHeight: px2dp(34),
      },
      toastStyle: {
        backgroundColor: '#33333380',
        minWidth: 45,
        justifyContent: 'center',
        alignItems: 'center',
      },
    });
    Filter.propTypes = {
      showToast: PropTypes.bool, //showToast类型: true 滑动以及点击时tosat展示点击内容,false 不展示
      toastStyle: PropTypes.object, //弹框样式
      toastTextStyle: PropTypes.object, //弹框字体样式
      allStyle: PropTypes.object, //外层样式
      contentStyle: PropTypes.object, //内层样式
      data: PropTypes.array, //筛选数据
      textStyle: PropTypes.object, //数据样式
      selectToIndex: PropTypes.func, //滑动或点击选中之后的方法回调
    };
    Filter.defaultProps = {
      showToast: true,
      toastStyle: {},
      toastTextStyle: {},
      allStyle: {},
      contentStyle: {},
      data: [],
      textStyle: {},
      selectToIndex: () => {},
    };
    
    
    3、调用案例,样式随意配置,不要介意我的审美
    <SectionList
                ref={ref => (this.sectionList = ref)}
                renderItem={this.renderItem}
                renderSectionHeader={({section: {first_character}}) => (
                  <View style={styles.headTitleView}>
                    <DUText style={styles.headTitleStyle}>{first_character}</DUText>
                  </View>
                )}
                sections={list}
                keyExtractor={(item, index) => item + index}
                ItemSeparatorComponent={this.ItemSeparatorComponent}
                stickySectionHeadersEnabled={true}
                showsVerticalScrollIndicator={false}
              />
    <Filter
            data={data}
              showToast={true}
              allStyle={{right: 10}}
              contentStyle={{backgroundColor: 'yellow'}}
              toastStyle={{backgroundColor: 'red'}}
              textStyle={{color: 'red'}}
              toastTextStyle={{fontSize: 18, color: 'black'}}
              selectToIndex={index => {
                this.sectionList &&
                  this.sectionList.scrollToLocation({
                    sectionIndex: index,
                    itemIndex: 0,
                    viewPosition: 0,
                    animated: false,
                    //该项设置是针对sectionList 在安卓上头部元素无法指定的,px2dp(64)为list的header的高度
                    viewOffset: isAndroid() ? px2dp(64) : 0,
                  });
              }}
            />
    
    以上就是我的类似通讯录的定位筛选的功能代码,欢迎各位童鞋评论、指导,谢谢!

    相关文章

      网友评论

          本文标题:RN SectionList通讯录定位筛选

          本文链接:https://www.haomeiwen.com/subject/vtxscktx.html