在React Native中正确使用Animated API

时间:2018-12-11 11:46:19

标签: javascript reactjs react-native react-redux react-animated

在React Native中,我对Animated API还是很陌生。我经历了很多有关使用动画API的教程,似乎在每一个教程中,元素都被定位为绝对值,是否有必要将元素定位为绝对值?

我也制作了一段动画,但是它看起来有点毛病,我认为textinput之后的视图没有绝对位置,这可能会导致问题。可以在保持textinput位置绝对但其他元素通过flexbox定位的同时做我想做的动画吗?

这是代码

handleFocus = () => {
console.log('starting animation');
this.setState({
  isFocused: true
});
Animated.timing(this.isFromViewFocused, {
  toValue: 1,
  duration: 300
}).start();
}

handleBlur = () => {
console.log('Blurring');
this.setState({
  isFocused: false
});
Animated.timing(this.isFromViewFocused, {
  toValue: 0,
  duration: 300
}).start();
}

render() {
const labelStyle = {
  position: this.state.isFocused === true ? 'absolute' : 'relative',
  alignItems: 'center',
  width: this.isFromViewFocused.interpolate({
    inputRange: [0, 1],
    outputRange: [DEVICE_WIDTH * 0.45, DEVICE_WIDTH]
  }),
  left: this.isFromViewFocused.interpolate({
    inputRange: [0, 1],
    outputRange: [DEVICE_WIDTH * 0.03, 0]
  }),
  marginBottom: this.isFromViewFocused.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 80]
  }),
  top: this.isFromViewFocused.interpolate({
    inputRange: [0, 1],
    outputRange: [10, 0]
  }),
  borderWidth: this.isFromViewFocused.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 5]
  }),
  borderColor: 'black',
  paddingTop: this.state.isFocused === true ? 20 : 0
 };
return (
  <View style={styles.container}>
    <ScrollView style={{ flex: 1 }} keyboardDismissMode='on-drag'>

      <Animated.View
      style={labelStyle}
      >

        <TextInput
        onFocus={this.handleFocus}
        onBlur={this.handleBlur}
        style={{
          borderColor: 'black',
          borderWidth: 1,
          width: '90%'
        }}
        >
          <Text>Hey Text</Text>
        </TextInput>
      </Animated.View>

      <Animated.View
      style={[styles.LocationContainer,
        { marginTop: this.isFromViewFocused.interpolate({
          inputRange: [0, 1],
          outputRange: [20, 80]
        })
      }
    ]}>

1 个答案:

答案 0 :(得分:1)

absolute定位与lefttopbottomright结合使用对性能不利。这就是为什么您的动画看起来很“浮躁”的原因。

使用转换会更好,这样您的组件保持relative并可以进行本机优化(与CSS3转换相同)。

此外,当使用非本机优化的属性(例如您使用的属性)时,不能将useNativeDriver设置为true。这会使性能更差。

要添加该内容,您不能(或不应)基于布尔值进行插值。 AnimatedJS为您提供了一个Animated.Value类,旨在简化插值操作。

这是一个更简单的动画示例:

export class MyAnimatedComponent extends React.Component {

  state = {
    animatedValue: new Animated.Value(0);
  }

  focus = () => {
    const { animatedValue } = this.state;
    Animated.timing(animatedValue, {
      duration: 280,
      toValue: 1,

      // This will make your animation glitch-free/performant.
      useNativeDriver: true,
    }).start();
  }

  blur = () => {
    Animated.timing(animatedValue, {
      duration: 140,
      toValue: 0,

      // This will make your animation glitch-free/performant.
      useNativeDriver: true,
    }).start();
  }

  render () {
    const { animatedValue } = this.state;
    const animatedStyles = {
      transform: [
        {
          // Move the div by 120px to the left when value === 1
          translateX: animatedValue.interpolate(
            inputRange: [0, 1],
            outputRange: [0, -120],

            // Tells Animated to never go outside of the outputRange
            extrapolate: 'clamp',
          ) 
        },
        {
          translateY: animatedValue.interpolate(
            inputRange: [0, 1],
            outputRange: [0, -50],
            extrapolate: 'clamp',
          )
        }
      ]
    }

    return (
      <View style={styles.wrapper}>
        <Animated.View style={animatedStyles} onFocus={onFocus} onBlur={onBlur}>
          I'm some content into an Animated div.
        </Animated.View>
      </View>
    )
  }
}