Почему анимированные toValue реагируют на родной не работает должным образом? - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь использовать Animated API от react-native.Я хочу сделать компонент, который выглядит как аккордеон (это ради попытки 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 голосов
/ 22 мая 2019

, как говорит @hardworker в комментарии, поэтому я стараюсь поставить проверку перед setState из maxHeight и minHeight. Для предотвращения изменения состояния 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,
       });
   }
}
...