react-native-komect-uikit
Version:
React Native UI Toolkit
181 lines (154 loc) • 4.87 kB
JavaScript
/**
* @Author: will
* @Date: 2017-06-19T17:49:44+08:00
* @Filename: OverlayPullView.js
* @Last modified by: will
* @Last modified time: 2017-06-20T14:23:30+08:00
*/
// OverlayPullView.js
'use strict';
import React, {Component, PropTypes} from "react";
import {Animated, View} from 'react-native';
import Theme from '../themes/Theme';
import TopView from './TopView';
import OverlayView from './OverlayView';
export default class OverlayPullView extends OverlayView {
static propTypes = {
...OverlayView.propTypes,
side: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
containerStyle: View.propTypes.style,
rootTransform: PropTypes.oneOfType([
PropTypes.oneOf(['none', 'translate', 'scale']),
PropTypes.arrayOf(PropTypes.shape({
translateX: PropTypes.number,
translateY: PropTypes.number,
scaleX: PropTypes.number,
scaleY: PropTypes.number,
})),
]),
};
static defaultProps = {
...OverlayView.defaultProps,
side: 'bottom',
animated: true,
rootTransform: 'none',
};
constructor(props) {
super(props);
this.viewLayout = {x: 0, y: 0, width: 0, height: 0};
Object.assign(this.state, {
marginValue: new Animated.Value(0),
showed: false,
});
}
get appearAnimates() {
let animates = super.appearAnimates;
animates.push(
Animated.spring(this.state.marginValue, {
toValue: 0,
friction: 9,
})
);
return animates;
}
get disappearAnimates() {
let animates = super.disappearAnimates;
animates.push(
Animated.spring(this.state.marginValue, {
toValue: this.marginSize,
friction: 9,
})
);
return animates;
}
get appearAfterMount() {
return false;
}
get marginSize() {
let {side} = this.props;
if (side === 'left' || side === 'right') return -this.viewLayout.width;
else return -this.viewLayout.height;
}
get rootTransformValue() {
let {side, rootTransform} = this.props;
if (!rootTransform || rootTransform === 'none') {
return [];
}
let transform;
switch (rootTransform) {
case 'translate':
switch (side) {
case 'top': return [{translateY: this.viewLayout.height}];
case 'left': return [{translateX: this.viewLayout.width}];
case 'right': return [{translateX: -this.viewLayout.width}];
default: return [{translateY: -this.viewLayout.height}];
}
break;
case 'scale':
return [{scaleX: Theme.overlayRootScale}, {scaleY: Theme.overlayRootScale}];
default:
return rootTransform;
}
}
appear(animated = this.props.animated) {
if (animated) {
this.state.marginValue.setValue(this.marginSize);
}
super.appear(animated);
let {rootTransform} = this.props;
if (rootTransform && rootTransform !== 'none') {
TopView.transform(this.rootTransformValue, animated);
}
}
disappear(animated = this.props.animated) {
let {rootTransform} = this.props;
if (rootTransform && rootTransform !== 'none') {
TopView.restore(animated);
}
super.disappear(animated);
}
onLayout(e) {
this.viewLayout = e.nativeEvent.layout;
if (!this.state.showed) {
this.setState({showed: true});
this.appear();
}
}
buildProps() {
super.buildProps();
let {side, style, containerStyle, ...others} = this.props;
let sideStyle, contentStyle;
//Set flexDirection so that the content view will fill the side
switch (side) {
case 'top':
sideStyle = {flexDirection: 'column', justifyContent: 'flex-start', alignItems: 'stretch'};
contentStyle = {marginTop: this.state.marginValue};
break;
case 'left':
sideStyle = {flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'stretch'};
contentStyle = {marginLeft: this.state.marginValue};
break;
case 'right':
sideStyle = {flexDirection: 'row', justifyContent: 'flex-end', alignItems: 'stretch'};
contentStyle = {marginRight: this.state.marginValue};
break;
default:
sideStyle = {flexDirection: 'column', justifyContent: 'flex-end', alignItems: 'stretch'};
contentStyle = {marginBottom: this.state.marginValue};
}
style = [].concat(style).concat(sideStyle);
contentStyle.opacity = this.state.showed ? 1 : 0;
containerStyle = [{
backgroundColor: Theme.defaultColor,//rgba(0, 0, 0, 0)',
}].concat(containerStyle).concat(contentStyle);
this.props = {side, style, containerStyle, ...others};
}
renderContent() {
let {containerStyle, children} = this.props;
return (
<Animated.View style={containerStyle} onLayout={(e) => this.onLayout(e)}>
{children}
</Animated.View>
);
}
}