UNPKG

@uiw/react-native

Version:
98 lines 2.69 kB
import React, { useState } from 'react'; import { View, StyleSheet, Text, Animated } from 'react-native'; import Item from './item'; import Button from '../Button'; import Icon from '../Icon'; export default function MenuDropdown(props) { const [state, setState] = useState({ btnIcon: 'down', visibleMenu: false, listHeightValue: new Animated.Value(0), listHeight: 0 }); const { title = '菜单', children, size, ...btnProps } = props; const { btnIcon, listHeightValue, listHeight, visibleMenu } = state; const handleonPress = () => { setState({ ...state, visibleMenu: !visibleMenu, btnIcon: visibleMenu ? 'down' : 'up' }); if (visibleMenu) { animateClose(); } else { animateStart(); } }; const animateStart = () => { Animated.timing(listHeightValue, { toValue: 1, duration: 500, useNativeDriver: false // 动画值在不同的驱动方式之间是不能兼容的。因此如果你在某个动画中启用了原生驱动,那么所有和此动画依赖相同动画值的其他动画也必须启用原生驱动。 }).start(); }; const animateClose = () => { Animated.timing(listHeightValue, { toValue: 0, duration: 400, useNativeDriver: false // 动画值在不同的驱动方式之间是不能兼容的。因此如果你在某个动画中启用了原生驱动,那么所有和此动画依赖相同动画值的其他动画也必须启用原生驱动。 }).start(); }; const menuContainer = event => { const { height } = event.nativeEvent.layout; setState({ ...state, listHeight: height }); }; return <View style={[styles.menuBox, { height: listHeight + 50 }]}> <Button {...btnProps} color={btnProps.color} onPress={handleonPress} size={size}> <Text>{title}</Text> <Icon name={btnIcon} size={17} /> </Button> <Animated.View style={[styles.list, // eslint-disable-next-line { opacity: listHeightValue, height: listHeightValue.interpolate({ inputRange: [0, 1], outputRange: [0, listHeight || 5] }), top: size === 'large' ? 35 : size === 'small' ? 21 : 30 }]}> <View onLayout={menuContainer}>{children}</View> </Animated.View> </View>; } MenuDropdown.Item = Item; const styles = StyleSheet.create({ menuBox: {}, list: { position: 'absolute', zIndex: 1000, left: 0, right: 0, top: 0, height: 100, marginTop: 10, borderColor: '#ddd', borderWidth: 1, borderRadius: 1, backgroundColor: '#fff', overflow: 'hidden' } });