[React Native] 动画 · LayoutAnimatd 和 setNativeProps

LayoutAnimation

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

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

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

注意:在Android 上使用 LayoutAnimation 需要导入 UIManager 并启用:

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

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

效果:

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() ,就可以实现布局改变的动画。

setNativeProps

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

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

所以, 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,就能很明显的感受到它的优势了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值