[fa icon="calendar"] Publié le 24 January 2017 par Nicolas Djambazian


Last month, one of my coworkers linked me this post full of awesome app animations. She asked me: "Can we do that in react-native?". I answered : "Challenge Accepted!"

After some work, see below what I was able to produce in react-native: a nice transition from a component in a ListView to a full-page component.

tvShowPage.gif

You can find the code in my repository.

Here are my tips to help you achieve the same result!

Tip #1 : Do not use Animated

Animated is a fantastic low level API to do animation in react-native. But, as all low level APIs, it is a bit complex and generates a lot of unclear code.

Most of your animation can be made with LayoutAnimation and react-native-animatable. It is more high level and simpler to manipulate. I highly recommend using these instead, you'll be able to do most things in no time.

Tip #2 : Use the same component for all your animations

Having two different components or pages which share a transition is hard to achieve. You will also have to duplicate some knowledge between them. The easiest way is to change the style of some parts of your component to animate it.

This is the biggest drawback of animating that kind of page change. Because you will not have two distinct pages in your router, you will lose the back button handling.

Tip #3 : Use relative positioning

There is no fixed positioning in react-native. If, like me, you are in a ListView, you can't use position: 'absolute', top: 0 to move a component to the top of your page. The component will go at the top of your ListView, which is not where you are if you have scrolled.

Instead, you can use measureInWindow to know the position of your View in the page. For example :

class MyComponent  extends Component {

  onPress() {
    this.props.onPress();
    this.refs.container.measureInWindow((x, y) => this.setState({
      windowPos: { x, y },
    }));
  };


  render() {
    const containerPos = this.state.windowPos ? {
      position: 'relative',
      top: - this.state.windowPos.y + appStyle.navbar.height,
    } : {};

    return (
      <TouchableWithoutFeedback onPress={this.onPress}>
        <View style={[styles.container, containerPos]} ref="container">
            {content}
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

Tip #4 : Allow the parent to be aware of the animation

When you start to animate an element of a list, the ListView will need to be aware of the state change. You will have to fade out all the other elements and to disable the scroll. Don't forget to accept a onAnimationStart or a onPress callback from the parent.

Tip #5 : Handle the exit animation

Your entering animation might be awesome, but don't forget about the exiting animation! Care that if you are removing extra elements during the exit, you will not be able to animate it outside the LayoutAnimation.

In my example, I waited the end of the LayoutAnimation to hide the bottom text. Thanks to that, I can animate the exit with react-native-animatable.

class TvShowListItem extends Component {

  componentWillUpdate() {
    const animation = LayoutAnimation.create(500, 'easeInEaseOut', 'opacity');
    LayoutAnimation.configureNext(animation, () => this.setState({ exitEnded: true }));
  }

  onPress() {
    if (this.state.opened) {
      this.refs.description.fadeOutDownBig();
      return  this.setState({opened: false,  exitEnded: false});
    }
    this.setState({ opened: true });
  };


  render() {
    const { opened, exitEnded } = this.state;
    return (
      <TouchableWithoutFeedback onPress={this.onPress}>
        <View style={[styles.container, containerPos]} ref="container" >
          { content }
          { (opened || ! exitEnded) && (
            <Animatable.View
              animation="fadeInUpBig"
              style={styles.description}
              duration={800}
              ref="description"
              delay={400}
            >
              <Text style={styles.descriptionText}>{this.props.tvShow.overview}</Text>
            </Animatable.View>
          )}
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

Finally

This ends my 5 Tips to make a great component to page animation in React-native. Send your creations in the comment, I'd love to see them!


Liked this article? Interested in building an app with us?

Contact a React Native expert in Paris




Want to rate this article?
Submit Rating

Topics: React Native, Animation