Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does "Animated.createAnimatedComponent" work?

In the Component ProgressBarAndroid, there are props indeterminable={Boolean} which show to a user an animation of what it's going on. I would like to do almost the same on ProgressViewIOS. So I tried to Animate it with Animated...

I saw on docs of Animated method called 'createAnimatedComponent' which they use to create Animated.View

I tried so to create another Animated (Native) Component but it doesn't work at all. The animation should gradually raise fillValue to 20 % and continue with an original value from the media upload...

This is my Component

// ProgressBar.ios.js
// @flow
import { PropTypes } from 'react';
import Component from 'components/base/Component';
import { ProgressViewIOS, Animated } from 'react-native';

const AnimatedProgressViewIOS = Animated.createAnimatedComponent(ProgressViewIOS);

class ProgressBarIOS extends Component {

  static propTypes = {
    // Percentage (0 - 100)
    fill: PropTypes.number.isRequired,
  };

  constructor(props, context: any) {
    super(props, context);
    this.state = {
      fillValue: new Animated.Value(props.fill),
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.fill === 0) {
      Animated.timing(this.state.fillValue, { toValue: 0.2, duration: 500 }).start();
    } else if (nextProps.fill > 19) {
      this.state.fillValue.setValue(nextProps.fill / 100);
    }
  }

  shouldComponentUpdate(nextProps) {
    return this.props.fill !== nextProps.fill;
  }

  render() {
    return (
      <AnimatedProgressViewIOS
        style={{ alignSelf: 'stretch' }}
        progress={this.state.fillValue} />
    );
  }

}

export default ProgressBarIOS;

EDIT: AnimatedComponent is used to modify style only. Props could be passed as animated value but remember it is not a number!

like image 849
Liroo Pierre Avatar asked Aug 11 '16 14:08

Liroo Pierre


People also ask

How animations work in react native?

The folks at React Native allow you as a developer to provide a property called useNativeDriver as a boolean value when you're constructing an animation object. When set to true, React Native, before starting the animation, serializes the whole animation state and what needs to be done in the future.

What is animated API in react native?

Animated API​ Animated focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and start / stop methods to control time-based animation execution.

What is animated event?

Animated.event is used to map gestures like scrolling, panning or other events directly to Animated values.


1 Answers

Animated.createAnimatedComponent can animate a number of different properties, however only some properties are supported using the native driver, fortunately it appears progress on ProgressViewIOS is one of them.

Here is a working implementation of an animated ProgressViewIOS.

import * as React from 'react';
import { View, SafeAreaView } from 'react-native';
import { ProgressViewIOS, Animated } from 'react-native';

const AnimatedProgressViewIOS = Animated.createAnimatedComponent(
  ProgressViewIOS
);

export default function App() {
  const value = React.useRef(new Animated.Value(0));

  React.useEffect(() => {
    Animated.loop(
      Animated.timing(value.current, {
        duration: 2000,
        toValue: 1,
        useNativeDriver: true,
      })
    ).start();
  }, []);

  return (
    <SafeAreaView>
      <View style={{ padding: 20 }}>
        <AnimatedProgressViewIOS
          style={{ alignSelf: 'stretch' }}
          progress={value.current}
        />
      </View>
    </SafeAreaView>
  );
}

It's worth noting that ProgressViewIOS is now deprecated, but building your own progress view is very straight forward and requires just two Views with simple styling like this (expo snack):

import * as React from 'react';
import { View, SafeAreaView, StyleSheet, Button, Text } from 'react-native';
import { Animated } from 'react-native';

export default function App() {
  const [progress, setProgress] = React.useState(() => Math.random());

  return (
    <SafeAreaView>
      <View style={{ padding: 20 }}>
        <AnimatedProgressView progress={progress} />
        <Text style={{padding: 20, textAlign: 'center'}}>{Math.round(progress * 100)}%</Text>
        <Button title="Animate" onPress={() => setProgress(Math.random())} />
      </View>
    </SafeAreaView>
  );
}

function AnimatedProgressView({ progress, style }) {
  const value = React.useRef(new Animated.Value(0));
  const [width, setWidth] = React.useState(0);

  React.useEffect(() => {
    Animated.spring(value.current, { toValue: progress }).start();
  }, [progress]);

  return (
    <View
      style={[styles.track, style]}
      onLayout={(event) => setWidth(event.nativeEvent.layout.width)}>
      <Animated.View
        style={[
          styles.fill,
          {
            transform: [
              {
                translateX: value.current.interpolate({
                  inputRange: [0, 1],
                  outputRange: [-width, 0],
                  overflow: 'clamp',
                }),
              },
            ],
          },
        ]}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  track: {
    minHeight: 4,
    borderRadius: 2,
    overflow: 'hidden',
    backgroundColor: '#ddd',
  },
  fill: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'blue',
  },
});
like image 183
levi Avatar answered Oct 09 '22 15:10

levi