Tengo un elemento que controla la representación de un elemento secundario. (Un TouchableHighlight que establece algún estado en su onPress.) En el método componentDidMount del elemento secundario, construyo un Animated.spring y start. Esto funciona para la entrada, pero necesito hacer la misma animación al revés para salir (es como un cajón). componentWillUnmount se ejecuta demasiado rápido para que Animated.spring siquiera comience a funcionar.

¿Cómo manejaría la animación de la salida del niño?

9
frank 26 ene. 2016 a las 10:40

2 respuestas

La mejor respuesta

Implementé un componente FadeInOut que animará un componente hacia adentro o hacia afuera cuando su propiedad isVisible cambie. Lo hice porque quería evitar manejar explícitamente el estado de visibilidad en los componentes que deberían entrar / salir con una animación.

<FadeInOut isVisible={this.state.someBooleanProperty} style={styles.someStyle}>
  <Text>Something...</Text>
</FadeInOut>

Esta implementación usa un desvanecimiento retardado, porque lo uso para mostrar el indicador de progreso, pero puede cambiarlo para usar cualquier animación que desee, o generalizarlo para aceptar los parámetros de animación como accesorios:

'use strict';

import React from 'react-native';

const {
  View,
  Animated,
  PropTypes
} = React;

export default React.createClass({
  displayName: 'FadeInOut',
  propTypes: {
    isVisible: PropTypes.bool.isRequired,
    children: PropTypes.node.isRequired,
    style: View.propTypes.style
  },

  getInitialState() {
    return {
      view: this.props.children,
      opacity: new Animated.Value(this.props.isVisible ? 1 : 0)
    };
  },

  componentWillReceiveProps(nextProps) {
    const isVisible = this.props.isVisible;
    const shouldBeVisible = nextProps.isVisible;

    if (isVisible && !shouldBeVisible) {
      Animated.timing(this.state.opacity, {
        toValue: 0,
        delay: 500,
        duration: 200
      }).start(this.removeView);
    }

    if (!isVisible && shouldBeVisible) {
      this.insertView();
      Animated.timing(this.state.opacity, {
        toValue: 1,
        delay: 500,
        duration: 200
      }).start();
    }
  },

  insertView() {
    this.setState({
      view: this.props.children
    });
  },

  removeView() {
    this.setState({
      view: null
    });
  },

  render() {
    return (
      <Animated.View
        pointerEvents={this.props.isVisible ? 'auto' : 'none'}
        style={[this.props.style, {opacity: this.state.opacity}]}>
        {this.state.view}
      </Animated.View>
    );
  }
});
10
jevakallio 26 ene. 2016 a las 23:22

Creo que tienes la propiedad de la animación invertida. Si mueve su lógica de animación al padre que abre y cierra al hijo, el problema se vuelve mucho más simple. En lugar de comenzar la animación en componentDidMount, hágalo con un clic de su TouchableHighlight además de, pero independientemente de, cualquier manipulación de accesorios en el niño que necesite hacer.

Luego, cuando el usuario hace clic para cerrar, simplemente puede revertir la animación como de costumbre y ni siquiera necesita descargarla. Además, esto le permitiría tener un cajón reutilizable (lo que se desliza hacia arriba y hacia abajo) y se abstrae del contenido que contiene. Por lo tanto, puede tener un único mecanismo de cajón que admita múltiples tipos diferentes de contenido.

2
Adam Terlson 26 ene. 2016 a las 16:09