[React Native] 动画 · LayoutAnimatd 和 setNativeProps

LayoutAnimation

对于一些既定的界面元素,图片、文字、滚动视图等动画效果,咱们会优先选择 Animated 来进行处理。可是若是你的动画效果须要改变布局,涉及到其余的 View 或者节点元素。那么就应该优先考虑 LayoutAnimation 来实现了。spring

较之于 Animated,LayoutAnimation 的使用要更简单。 若是你用 state 记录并改变过某一 View 的高度,那么在此基础上只须要调用一下LayoutAnimation 的动画函数,并保证父节点是 flex 布局的,就能够实现这一高度变化的动画。函数

动画类型:

  • easeInEaseOut() 先加速至全速,再逐渐减速渐停
  • linear() 线性动画,保持均速
  • spring() 弹性模型,有一个反复回弹的效果

注意:在Android 上使用 LayoutAnimation 须要导入 UIManager 并启用:工具

UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);布局

[动画1 - 改变布局高度,将同级 View 往下推]性能

效果:flex

layout

实现:动画

UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);

export default class LayoutAnimated extends Component {
  state = {
    moreHeight: 0,					//动态高度
  };
  _onPress = () => {
    LayoutAnimation.spring();   	//调用 LayoutAnimation 动画
    this.setState({moreHeight: this.state.moreHeight === 0 ? 100 : 0})
  }

  render() {
    return (
      <View style={{flex: 1, paddingHorizontal: 20}}>
        <View style={styles.card_view}>
          <TouchableOpacity onPress={this._onPress}>	// 为看到点击效果,不在 Text中实现 onPress
            <Text style={styles.more_text}>查看更多</Text>
          </TouchableOpacity>
          <View style={{height: this.state.moreHeight}}/>  //变量直接设定给 View
        </View>
        <View style={{backgroundColor: '#e29fae', height: 100}}/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  card_view: {backgroundColor: '#ebde5d', marginTop: 20},
  more_text: {textAlign: 'right', paddingVertical: 8, borderBottomColor: '#ccc', borderBottomWidth: 1},
});
复制代码

可见,外部布局是弹性布局的时候,在 setState 的基础上调用一次 LayoutAnimation.spring() ,就能够实现布局改变的动画。this

setNativeProps

若是使用的动画,须要频繁地刷新,进行 setState,就一定会影响到性能。 此时能够尝试使用 setNativeProps 来进行修改 ,该方法直接修改基于原生视图的组件的属性来达到效果。spa

这种直接操做组件的操做并非应该常常使用的工具。 通常只是用来建立连续的动画,同时避免渲染组件结构和同步太多视图变化所带来的大量开销。 setNativeProps 是一个“简单粗暴”的方法,它直接在底层(DOM、UIView 等)而不是 Rea ct 组件中记录 state,这样会使代码逻辑难以理清。因此在使用这个方法以前,请尽可能先尝试用 setState 和 shouldComponentUpdate 方法来解决问题。 (引用自官方文档)code

因此, setNativeProps 是一个强大但也是不得已而为之的选择。

[动画2 - setNativeProps 实现头部栏透明度渐变 ]

有时咱们会须要在列表视图滚动的时候,头部栏有一个透明度渐变的效果。在滑动到必定的距离以后,头部栏再也不透明。

header

通常思路是这样,重写 ScrollView 的 onScroll 方法,判断当前所处的 y 值,并经过当前 y 值所处范围计算出应该设置的透明度。可是若是此时用 state 记录透明度,setState 完成设置刷新的话,开销的巨大的,甚至致使必定的卡顿 [onScroll 的触发十分频繁 (scrollEventThro 能够改变 onScroll 调用频率但不推荐)]。因此这里咱们应该选择的是 setNativeProps。

实现:

<View										//头部view ,设定 ref
    ref={head => this.headerView = head}
	...
  </View>
复制代码

在滑动的 y 值在(50,100] 之间的时候,设置透明度为 y/100 。这样在 50 如下都是 0.5 半透明, 100 日后透明度都是 1,即不透明。

//ScrollView 的 onScroll 方法
  onScroll = ({nativeEvent, contentOffset}) => {
    // console.info('nativeEvent', nativeEvent);
    const currentY = nativeEvent.contentOffset.y;
    if (currentY > 50 && currentY <= 100) {
      this.headerView.setNativeProps({
        style: {opacity: currentY / 100}
      })
    }
  }
复制代码

能够看到,setNativeProps 在这个场景中仍是很是适用的,若是你体验过 setState,就能很明显的感觉到它的优点了。

相关文章
相关标签/搜索