美文网首页
React-native分享类似美团下拉菜单Demo

React-native分享类似美团下拉菜单Demo

作者: HT_Jonson | 来源:发表于2018-05-18 16:19 被阅读0次

    上图:


    image.png

    这个Demo我已经做了一些处理,所以,有需要的朋友可以自己更改
    下面放出源码

    /**
     * 
     * 皓天
     * @memberOf ActionBar
     */
    import React, { Component } from "react";
    import {
      View,
      Text,
      TouchableHighlight,
      Image,
      TouchableOpacity,
      ScrollView,
      Animated,
      Easing,
      StyleSheet
    } from "react-native";
    import PropTypes from "prop-types";
    
    class ActionBar extends Component {
      constructor(props, context) {
        super(props, context);
    
        var selectIndex = new Array(this.props.data.length);
        for (var i = 0; i < selectIndex.length; i++) {
          selectIndex[i] = 0;
        }
        this.state = {
          activityIndex: -1,
          selectIndex: selectIndex,
          rotationAnims: props.data.map(() => new Animated.Value(0))
        };
    
        this.defaultConfig = {
          bgColor: "grey",
          tintColor: "#333333",
          activityTintColor: "red",
          arrowImg: require("./img/dropdown_arrow.png"),
          checkImage: require("./img/menu_check.png")
        };
      }
    
      renderChcek(index, title) {
        var activityIndex = this.state.activityIndex;
        if (this.state.selectIndex[activityIndex] == index) {
          var checkImage = this.props.checkImage
            ? this.props.checkImage
            : this.defaultConfig.checkImage;
          return (
            <View
              style={{
                flex: 1,
                justifyContent: "space-between",
                alignItems: "center",
                paddingHorizontal: 15,
                flexDirection: "row"
              }}
            >
              <Text
                style={[
                  styles.item_text_style,
                  this.props.optionTextStyle,
                  {
                    color: this.props.activityTintColor
                      ? this.props.activityTintColor
                      : this.defaultConfig.activityTintColor
                  }
                ]}
              >
                {title}
              </Text>
              <Image
                source={checkImage}
                style={{
                  tintColor: this.props.activityTintColor
                    ? this.props.activityTintColor
                    : this.defaultConfig.activityTintColor
                }}
              />
            </View>
          );
        } else {
          return (
            <View
              style={{
                flex: 1,
                justifyContent: "space-between",
                alignItems: "center",
                paddingHorizontal: 15,
                flexDirection: "row"
              }}
            >
              <Text
                style={[
                  styles.item_text_style,
                  this.props.optionTextStyle,
                  {
                    color: this.props.tintColor
                      ? this.props.tintColor
                      : this.defaultConfig.tintColor
                  }
                ]}
              >
                {title}
              </Text>
            </View>
          );
        }
      }
    
      renderActivityPanel() {
        if (this.state.activityIndex >= 0) {
          var currentTitles = this.props.data[this.state.activityIndex];
    
          var heightStyle = {};
          if (
            this.props.maxHeight &&
            this.props.maxHeight < currentTitles.length * 44
          ) {
            heightStyle.height = this.props.maxHeight;
          }
    
          return (
            <View
              style={{
                position: "absolute",
                left: 0,
                right: 0,
                top: 40,
                bottom: 0
              }}
            >
              <TouchableOpacity
                onPress={() => this.openOrClosePanel(this.state.activityIndex)}
                activeOpacity={1}
                style={{
                  position: "absolute",
                  left: 0,
                  right: 0,
                  top: 0,
                  bottom: 0
                }}
              >
                <View style={{ opacity: 0.4, backgroundColor: "black", flex: 1 }} />
              </TouchableOpacity>
    
              <ScrollView
                style={[
                  {
                    position: "absolute",
                    top: 0,
                    left: 0,
                    right: 0,
                    backgroundColor: "white"
                  },
                  heightStyle
                ]}
              >
                {currentTitles.map((title, index) => (
                  <TouchableOpacity
                    key={index}
                    activeOpacity={1}
                    style={{ flex: 1, height: 44 }}
                    onPress={this.itemOnPress.bind(this, index)}
                  >
                    {this.renderChcek(index, title)}
                    <View
                      style={{
                        backgroundColor: "#F6F6F6",
                        height: 1,
                        marginLeft: 15
                      }}
                    />
                  </TouchableOpacity>
                ))}
              </ScrollView>
            </View>
          );
        } else {
          return null;
        }
      }
    
      openOrClosePanel(index) {
        this.props.bannerAction ? this.props.bannerAction() : null;
    
        if (this.state.activityIndex == index) {
          this.closePanel(index);
          this.setState({
            activityIndex: -1
          });
        } else {
          if (this.state.activityIndex > -1) {
            this.closePanel(this.state.activityIndex);
          }
          this.openPanel(index);
          this.setState({
            activityIndex: index
          });
        }
      }
    
      openPanel(index) {
        Animated.timing(this.state.rotationAnims[index], {
          toValue: 0.5,
          duration: 300,
          easing: Easing.linear
        }).start();
      }
    
      closePanel(index) {
        Animated.timing(this.state.rotationAnims[index], {
          toValue: 0,
          duration: 300,
          easing: Easing.linear
        }).start();
      }
    
      split(data){
        return data.length > 6 ? data.substring(0,6) + '...' : data
      }
    
      itemOnPress(index) {
        if (this.state.activityIndex > -1) {
          var selectIndex = this.state.selectIndex;
          selectIndex[this.state.activityIndex] = index;
          this.setState({
            selectIndex: selectIndex
          });
          if (this.props.handler) {
            this.props.handler(this.state.activityIndex, index);
          }
        }
        this.openOrClosePanel(this.state.activityIndex);
      }
    
      renderDropDownArrow(index) {
        var icon = this.props.arrowImg
          ? this.props.arrowImg
          : this.defaultConfig.arrowImg;
        return (
          <Animated.Image
            source={icon}
            style={{
              width: 6,
              height: 4,
              marginLeft: 8,
              tintColor:
                index === this.state.activityIndex
                  ? this.props.activityTintColor
                    ? this.props.activityTintColor
                    : this.defaultConfig.activityTintColor
                  : this.props.tintColor
                    ? this.props.tintColor
                    : this.defaultConfig.tintColor,
              transform: [
                {
                  rotateZ: this.state.rotationAnims[index].interpolate({
                    inputRange: [0, 1],
                    outputRange: ["0deg", "360deg"]
                  })
                }
              ]
            }}
          />
        );
      }
    
      render() {
        
        return (
          <View style={{ flexDirection: "column", flex: 1 }}>
            <View
              style={{
                flexDirection: "row",
                backgroundColor: this.props.bgColor
                  ? this.props.bgColor
                  : this.defaultConfig.bgColor
              }}
            >
              {this.props.data.map((rows, index) => (
                <TouchableOpacity
                  activeOpacity={1}
                  onPress={this.openOrClosePanel.bind(this, index)}
                  key={index}
                  style={{
                    flex: 1,
                    height: 48,
                    alignItems: "center",
                    justifyContent: "center"
                  }}
                >
                  <View
                    style={{
                      flexDirection: "row",
                      alignItems: "center",
                      justifyContent: "center",
                    }}
                  >
                    <Text
                      style={[
                        styles.title_style,
                        this.props.titleStyle,
                        {
                          color:
                            index === this.state.activityIndex
                              ? this.props.activityTintColor
                                ? this.props.activityTintColor
                                : this.defaultConfig.activityTintColor
                              : this.props.tintColor
                                ? this.props.tintColor
                                : this.defaultConfig.tintColor
                        }
                      ]}
                    >
                      {/* {rows[this.state.selectIndex[index]]} */}
                      {this.split(rows[this.state.selectIndex[index]])}
                    </Text>
                    {this.renderDropDownArrow(index)}
                  </View>
                </TouchableOpacity>
              ))}
            </View>
            {this.props.children}
    
            {this.renderActivityPanel()}
          </View>
        );
      }
    }
    
    ActionBar.propTypes = {
      bgColor: PropTypes.string,
      tintColor: PropTypes.string,
      activityTintColor: PropTypes.string,
      arrowImg: PropTypes.number,
      checkImage: PropTypes.number,
      data: PropTypes.array,
      bannerAction: PropTypes.func,
      optionTextStyle: PropTypes.object,
      titleStyle: PropTypes.object,
      maxHeight: PropTypes.number
    };
    
    const styles = StyleSheet.create({
      title_style: {
        fontSize: 16
      },
      item_text_style: {
        color: "#333333",
        fontSize: 16
      }
    });
    
    export default ActionBar;
    
    

    下面是使用方法

      render() {
        var data = [["第一项目项目项目", "第二项目","1111111111"], ["第三项目", "第四项目","22222222222222"]];
        return (
          <View style={styles.container}>
            <ActionBar
              style={{ flex: 1 }}
              bgColor={"white"}
              tintColor={"#000000"}
              activityTintColor={"#3BB4F2"}
              // arrowImg={}
              // checkImage={}
              optionTextStyle={{ color: "#333333" }}
              titleStyle={{color: '#3BB4F2'}}
              // maxHeight={300}
              handler={(selection, row) =>
                // this.setState({ text: data[selection][row] })
                (HomeStore.firstName = data[selection][row])
              }
              data={data}
              // data={HomeStore.dataTest}
            >
              <View style={{ flex: 1 }}>
                <Text>{HomeStore.firstName} -------这里是选择的内容</Text>
              </View>
            </ActionBar>
          </View>
        );
      }
    

    相关文章

      网友评论

          本文标题:React-native分享类似美团下拉菜单Demo

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