ReactNativeUtil icon indicating copy to clipboard operation
ReactNativeUtil copied to clipboard

ViewMoreText

Open wuyunqiang opened this issue 8 years ago • 0 comments

/**
 * Created by wuyunqiang on 2017/7/11.
 */
import React from 'react';
import PropTypes from 'prop-types';
import { Text, View, Animated, LayoutAnimation, Platform, UIManager } from 'react-native';

const emptyFunc = () => {
};
const CustomLayoutAnimation = {
  duration: 10000,
  create: {
    type: LayoutAnimation.Types.linear,
    property: LayoutAnimation.Properties.opacity,
  },
  update: {
    type: LayoutAnimation.Types.easeInEaseOut,
  },
};
export default ViewMoreText = React.createClass({
  propTypes: {
    renderViewMore: PropTypes.func,
    renderViewLess: PropTypes.func,
    afterCollapse: PropTypes.func,
    afterExpand: PropTypes.func,
    numberOfLines: PropTypes.number.isRequired
  },
  isTruncated: false,
  originalHeight: 0,
  shouldShowMore: false,
  contentHeight: 0,
  isInit: false,

  getInitialState() {
    this.resetData();
    return {
      numberOfLines: null,
      opacity: 0,
    };
  },

  componentDidMount() {
    if (Platform.OS === 'android') {
      UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
    }
  },

  componentWillUpdate() {

  },

  componentDidUpdate() {
    if (this.state.numberOfLines === null) {
      (this.props.afterExpand || emptyFunc)();
    } else {
      (this.props.afterCollapse || emptyFunc)();
    }
  },

  resetData() {
    this.isTruncated = false;
    this.originalHeight = 0;
    this.shouldShowMore = false;
    this.isInit = false;
  },

  componentWillReceiveProps() {
    this.resetData();
    this.setState({
      numberOfLines: null,
      opacity: 0
    });
  },

  onLayout(event) {
    console.log('onLayout');
    const { x, y, width, height } = event.nativeEvent.layout;
    if (height === 0 || this.state.opacity === 1) return false;
    this.setOriginalHeight(height);
    this.checkTextTruncated(height);
    if (this.state.numberOfLines === this.props.numberOfLines) {
      this.setState({
        opacity: 1
      });
    }
  },

  setOriginalHeight(height) {
    if (this.originalHeight === 0) {
      this.originalHeight = height;

      this.setState({
        numberOfLines: this.props.numberOfLines
      });
    }
  },

  checkTextTruncated(height) {
    if (height < this.originalHeight) {
      this.shouldShowMore = true;
    }
  },

  onPressMore() {
    this.setState({
      numberOfLines: null
    });
  },

  onPressLess() {
    this.setState({
      numberOfLines: this.props.numberOfLines
    });
  },

  renderViewMore() {
    return (
      <Text onPress={this.onPressMore}>
                View More
            </Text>
    );
  },

  renderViewLess() {
    return (
      <Text onPress={this.onPressLess}>
                View Less
            </Text>
    );
  },

  renderFooter() {
    const {
            numberOfLines
        } = this.state;

    if (this.shouldShowMore === true) {
      if (numberOfLines > 0) {
        return (this.props.renderViewMore || this.renderViewMore)(this.onPressMore);
      }
      return (this.props.renderViewLess || this.renderViewLess)(this.onPressLess);
    }
  },

  render() {
    return (
      <View onLayout={this.onLayout} style={{ opacity: this.state.opacity }}>
        <Text
          numberOfLines={this.state.numberOfLines}
        >
          {this.props.children}
        </Text>
        {this.renderFooter()}

        {
                    this.state.numberOfLines &&
                    <View style={{ width: 1, height: 1 }} />
                }

      </View>
    );
  }

});

wuyunqiang avatar Jul 11 '17 10:07 wuyunqiang