为什么动画的toValue会对本机做出反应,无法正常工作?

时间:2019-05-22 07:06:52

标签: react-native animation react-animated

我尝试使用Animated中的react-native API。我想制作一个看起来像手风琴的组件(这是为了尝试Animated API。我知道我可以使用其他手风琴库)。动画有效,但是toValue不会随着内部内容的高度而扩展。到目前为止,这是我尝试过的操作:

Child.js

import React, { Component } from 'react';
import {
  Animated,
  View,
} from 'react-native';

class Child extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
      animation: null,
      maxHeight: '',
      minHeight: '',
    };
  }

  toggle = () => {
    const {
      expanded, maxHeight, minHeight,
    } = this.state;

    const initialValue = expanded ? maxHeight + minHeight : minHeight;
    const finalValue = expanded ? minHeight : maxHeight + minHeight;

    this.setState(prevState => ({
      expanded: !prevState.expanded,
    }));

    this.state.animation.setValue(initialValue);
    Animated.spring(
      this.state.animation,
      {
        toValue: finalValue,
        bounciness: 0,
      },
    ).start();
  }

  setMinHeight = (e) => {
    this.setState({
      minHeight: e.nativeEvent.layout.height,
      animation: new Animated.Value(e.nativeEvent.layout.height),
    });
  }

  setMaxHeight = (e) => {
    this.setState({
      maxHeight: e.nativeEvent.layout.height,
    });
  }

  render() {
    const { header, content } = this.props;
    const { animation } = this.state;

    return (
      <Animated.View style={{
        height: animation,
        overflow: 'hidden',
        width: '100%',
      }}
      >
        <View onLayout={e => this.setMinHeight(e)}>
          {header}
        </View>

        <View onLayout={e => this.setMaxHeight(e)}>
          {content}
        </View>
      </Animated.View>
    );
  }
}

export default Child;

App.js

import React, { Component, Fragment } from 'react';
import {
  ScrollView,
  View,
  Text,
  StyleSheet,
  Button,
} from 'react-native';
import { Row } from 'react-native-easy-grid';

// You can import from local files
import Child from './components/Child';

export default class App extends React.Component {
  render() {
    const header = (
      <Button
        title="press"
        onPress={() => this.toggle.toggle()}
      />
    );

    const content = (
      <Fragment>
        <View
          style={{
            width: 300,
            backgroundColor: 'green',
            padding: 20,
          }}
        >
          <View style={{ width: 'auto', padding: 10, backgroundColor: 'blue' }}>
            <Text>Content1</Text>
            <Text>Content2</Text>
            <Text>Content3</Text>
            // Please try to add more text here
          </View>
        </View>
      </Fragment>
    );
    return (
      <Fragment>
        <ScrollView style={[styles.container]}>
          <Row style={{ marginTop: 30 }}>
            <View style={[styles.view]}>
              <Child
                content={content}
                header={header}
                ref={(ref) => { this.toggle = ref; }}
              />
            </View>
          </Row>
        </ScrollView>
      </Fragment>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 15,
    backgroundColor: 'purple',
  },
  view: {
    flex: 1,
    backgroundColor: 'pink',
  },
});

我在这里想念什么?任何帮助都将非常有帮助和赞赏。谢谢!

更新 当我尝试将console.log(e.nativeEvent.layout.height)放在setMaxHeight内时,有时会显示不同的值。这怎么可能发生?

1 个答案:

答案 0 :(得分:0)

正如@hardworker在评论中所说,因此我尝试将验证放在maxHeight和minHeight的setState之前。为了防止在初始渲染后maxHeight和minHeight的状态发生变化。这是工作代码:

setMinHeight = (e) => {
   if(this.state.minHeight === '') {
       this.setState({
         minHeight: e.nativeEvent.layout.height,
         animation: new Animated.Value(e.nativeEvent.layout.height),
       });
   }
}

setMaxHeight = (e) => {
   if (this.state.maxHeight === '') {
       this.setState({
         maxHeight: e.nativeEvent.layout.height,
       });
   }
}