我想创建一个类似于uber的导航抽屉。那么,有没有我可以用来基于React Router 4开发应用导航抽屉的库或软件包?
答案 0 :(得分:0)
使用此
https://github.com/Tinysymphony/react-native-drawer-menu
https://github.com/root-two/react-native-drawer
您可以自己创建视图,这并不容易,就像这样:
import React, { PureComponent } from 'react';
import {
View,
Animated,
Easing,
Dimensions,
TouchableOpacity,
TouchableWithoutFeedback
} from 'react-native';
import mitt from 'mitt';
import styled from 'styled-components';
import { t } from '../i18n';
import { TOOLBAR_HEIGHT } from './Toolbar';
import Avatar from '../components/Avatar';
import Icon from '../components/Icon';
import Text from './Text';
const { width } = Dimensions.get('window');
//-----------------------------------------------
class MenuDrawer extends PureComponent {
static defaultProps = {
width: (width * 75) / 100
};
constructor(props) {
super(props);
this.state = { show: false };
this.emitter = mitt();
this.animateValue = {
opacity: new Animated.Value(0),
marginLeft: new Animated.Value(-props.width)
};
}
animation({ opacity, mgleft }) {
this.animateValue.opacity.setValue(opacity.start);
this.animateValue.marginLeft.setValue(mgleft.start);
return Animated.parallel([
Animated.timing(this.animateValue.opacity, {
toValue: opacity.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.timing(this.animateValue.marginLeft, {
toValue: mgleft.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
})
]);
}
subscribe = cb => {
this.emitter.on('state-change', status => {
cb(status);
});
};
show = () => {
this.emitter.emit('state-change', true);
this.setState({ ...this.state, show: true }, () => {
const opacity = { start: 0, end: 0.6 };
const mgleft = { start: this.props.width, end: 0 };
this.animation({ opacity, mgleft }).start();
});
};
hide = () => {
this.emitter.emit('state-change', false);
const opacity = { start: 0.6, end: 0 };
const mgleft = { start: 0, end: this.props.width };
this.animation({ opacity, mgleft }).start(({ finished }) => {
if (finished) {
this.setState({ ...this.state, show: false });
}
});
};
handlePressOnBackground = () => {
this.hide();
};
renderContent() {
const { me } = this.props;
const name = me.fullname;
const avatar_url = me.avatar_url;
return (
<StyledView>
<StyledMyInfo>
<Avatar size={96} uri={avatar_url} name={name} isAgent={true} />
<StyledName text={name} />
</StyledMyInfo>
<StyledMenu>
<TouchableOpacity onPress={this.props.handlePressSettings}>
<StyledMenuItem>
<StyledIcon>
<Icon size={20} source={require('../assets/setting.png')} />
</StyledIcon>
<StyledLabel text={t('general_settings')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressChangePassword}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={2}
source={require('../assets/password.png')}
/>
</StyledIcon>
<StyledLabel text={t('profile_language_change_password_link')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressLogout}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={-1}
source={require('../assets/logout.png')}
/>
</StyledIcon>
<StyledLabel text={t('agent_profile_logout')} />
</StyledMenuItem>
</TouchableOpacity>
</StyledMenu>
</StyledView>
);
}
render() {
const { id } = this.props.me;
if (!this.state.show || !id) return null;
return (
<StyledViewContainer>
<TouchableWithoutFeedback
style={{ flex: 1 }}
onPress={this.handlePressOnBackground}
>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: 'black'
},
{ opacity: this.animateValue.opacity }
]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
width: '75%'
},
{ marginLeft: -this.animateValue.marginLeft }
]}
>
{this.renderContent()}
</Animated.View>
</StyledViewContainer>
);
}
}
//-----------------------------------------------
const StyledViewContainer = styled(View)`
position: absolute;
top: ${TOOLBAR_HEIGHT};
right: 0;
bottom: 0;
left: 0;
`;
const StyledView = styled(View)`
flex: 1;
background-color: #f9f9f9;
`;
const StyledMyInfo = styled(View)`
justify-content: center;
align-items: center;
height: 240;
background-color: white;
`;
const StyledName = styled(Text)`
margin-top: 10px;
font-size: ${props => props.theme.fontSizeLarge};
font-family: ${props => props.theme.fontSemiBold};
`;
const StyledMenu = styled(View)`
padding: 12px 15px;
`;
const StyledMenuItem = styled(View)`
margin-bottom: 5px;
flex-direction: row;
align-items: center;
`;
const StyledIcon = styled(View)`
width: 40;
height: 40;
justify-content: center;
align-items: center;
`;
const StyledLabel = styled(Text)``;
export default MenuDrawer;