【React-Native】自定义Drawer(抽屉)动画组件

自己实现一个简单的抽屉组件


因为业务需要实现侧滑抽屉菜单,看了一眼项目中封装的DrawerLayout组件,便直接引用准备使用,但是使用后却发现并没有理想中的动画效果,便打开组件代码看了一眼,发现之前的作者是直接用Modal写的,然后在modal里写了一个蒙层和一个View容器: 大概布局为:

<Modal>
	<Animated.View>
		<View>{此处作为蒙层,点击关闭抽屉用}</View>
	</Animated.View>
	<View>{this.props.children}</View>
</Modal>

总之组件似乎写法有问题,只有弹框没有动画效果,改吧改吧应该就可以了,于是开始修改了的过程,经过了半个小时的努力,总算是改好了,但是动画效果并不是我预想中的样子,于是决定放弃使用项目中别人写的组件。

日常打开我们的老朋友,度娘,搜索了一下React-native 抽屉组件,要么是让安装第三方的库,要么是一些涉及到原生应用的帖子(表示看不懂),要么还有一些收费的帖子,一无所获,干脆决定自己写吧,这么简单的功能就是怕麻烦,想找个现成的粘贴得了,奈何不允许我偷懒。废话不多说,直接码代码:

/**
 * @Author: small_axe
 * @描述: 抽屉动画
 * @Date: 2021/05/26
 */

import React, {useState, useEffect, useCallback} from 'react';
import {Animated, StyleSheet, Dimensions} from 'react-native';
import PropTypes from 'prop-types';
const WINDOW = Dimensions.get('window');

const AWSDrawerMenu = props => {
  const {visible, duration, onShow, dismiss, menuPosition} = props;

  const [animateValue, setAnimateValue] = useState(new Animated.Value(0));

  useEffect(() => {
    if (visible) {
      _onShow();
    } else {
      _dismiss();
    }
  }, [_onShow, visible, _dismiss]);

  // eslint-disable-next-line react-hooks/exhaustive-deps
  const _onShow = () => {
    if (onShow) {
      onShow();
    }
    animate(1);
  };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  const _dismiss = () => {
    if (dismiss) {
      dismiss();
    }
    animate(0);
  };

  // 添加动画效果
  const animate = toValue => {
    Animated.timing(animateValue, {
      toValue: toValue,
      duration: duration,
      useNativeDriver: true,
      friction: 9,
    }).start();
  };

  // 判断position从不同位置唤出抽屉
  const getPosition = useCallback(() => {
    switch (menuPosition) {
      case 'left':
        return {
          translateX: animateValue.interpolate({
            inputRange: [0, 1],
            outputRange: [-WINDOW.width, 0],
          }),
        };
      case 'right':
        return {
          translateX: animateValue.interpolate({
            inputRange: [0, 1],
            outputRange: [WINDOW.width, 0],
          }),
        };
      case 'top':
        return {
          translateY: animateValue.interpolate({
            inputRange: [0, 1],
            outputRange: [-WINDOW.height, 0],
          }),
        };
      case 'bottom':
        return {
          translateY: animateValue.interpolate({
            inputRange: [0, 1],
            outputRange: [WINDOW.height, 0],
          }),
        };
      default:
        return {
          translateX: animateValue.interpolate({
            inputRange: [0, 1],
            outputRange: [-WINDOW.width, 0],
          }),
        };
    }
  }, [animateValue, menuPosition]);

  return (
    <Animated.View
      style={[
        styles.container,
        {
          transform: [getPosition()],
        },
      ]}>
      {props.children}
    </Animated.View>
  );
};

AWSDrawerMenu.propTypes = {
  visible: PropTypes.bool, // 控制抽屉显影状态
  duration: PropTypes.number, // 动画持续时间
  onShow: PropTypes.func, // 显示
  dismiss: PropTypes.func, // 影藏
  menuPosition: PropTypes.oneOf(['left', 'right', 'top', 'bottom']), // 抽屉出现的位置
};

AWSDrawerMenu.defaultProps = {
  visible: false,
  duration: 500,
  onShow: () => {},
  dismiss: () => {},
  menuPosition: 'left',
};

module.exports = AWSDrawerMenu;

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
    zIndex: 1000,
    backgroundColor: '#fff',
  },
});

大功告成,然后就是应用走一波,很好的满足了菜单从各个方向实现抽屉动画的效果。

只是简单写了一个实现抽屉效果的动画容器,使用的时候用此组件包裹你的内容组件,就可实现抽屉的动画效果。觉得有帮到你的同学记得点个赞。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果 react-native-echarts-pro 组件React Native 中的图表溢出容器,可以通过以下两种方法进行解决: 1.设置容器的大小 可以在容器组件中设置宽度和高度,然后将宽度和高度作为 props 传递给 react-native-echarts-pro 组件。例如: ``` import React from 'react'; import { View, Dimensions } from 'react-native'; import Echarts from 'react-native-echarts-pro'; const windowWidth = Dimensions.get('window').width; const windowHeight = Dimensions.get('window').height; export default function App() { return ( <View style={{ width: windowWidth, height: windowHeight }}> <Echarts option={option} width={windowWidth} // 设置宽度 height={windowHeight} // 设置高度 /> </View> ); } ``` 2.使用 onLayout 事件设置图表的大小 可以在 react-native-echarts-pro 组件中使用 onLayout 事件来获取容器组件的宽度和高度,然后将宽度和高度设置给图表。例如: ``` import React, { useState } from 'react'; import { View, Dimensions } from 'react-native'; import Echarts from 'react-native-echarts-pro'; export default function App() { const [chartWidth, setChartWidth] = useState(0); const [chartHeight, setChartHeight] = useState(0); const onLayout = event => { const { width, height } = event.nativeEvent.layout; setChartWidth(width); setChartHeight(height); }; return ( <View style={{ flex: 1 }} onLayout={onLayout}> <Echarts option={option} width={chartWidth} height={chartHeight} /> </View> ); } ``` 以上两种方法均可将 react-native-echarts-pro 组件的大小设置为自适应容器的大小。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

small_Axe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值