closing animation in renderers

This commit is contained in:
Martin Bielik 2017-01-05 17:52:10 +01:00
parent cc2cfb7c75
commit 6284a3502e
3 changed files with 44 additions and 11 deletions

View File

@ -11,6 +11,8 @@ const layoutsEqual = (a, b) => (
a === b || (a && b && a.width === b.width && a.height === b.height) a === b || (a && b && a.width === b.width && a.height === b.height)
); );
const isFunctional = Component => !Component.prototype.render;
export default class MenuContext extends Component { export default class MenuContext extends Component {
constructor(props) { constructor(props) {
@ -47,14 +49,17 @@ export default class MenuContext extends Component {
closeMenu() { closeMenu() {
debug('close menu'); debug('close menu');
this._menuRegistry.getAll().forEach(menu => { const closeAnimation = (this.refs.menuOptions && this.refs.menuOptions.close) || Promise.resolve;
if (menu.instance._getOpened()) { closeAnimation().then(() => {
menu.instance._setOpened(false); this._menuRegistry.getAll().forEach(menu => {
// invalidate trigger layout if (menu.instance._getOpened()) {
this._menuRegistry.updateLayoutInfo(menu.name, { triggerLayout: undefined }); menu.instance._setOpened(false);
} // invalidate trigger layout
}); this._menuRegistry.updateLayoutInfo(menu.name, { triggerLayout: undefined });
this._notify(); }
});
this._notify();
})
} }
toggleMenu(name) { toggleMenu(name) {
@ -166,7 +171,11 @@ export default class MenuContext extends Component {
const style = [optionsContainerStyle, customStyles.optionsContainer]; const style = [optionsContainerStyle, customStyles.optionsContainer];
const layouts = { windowLayout, triggerLayout, optionsLayout }; const layouts = { windowLayout, triggerLayout, optionsLayout };
const props = { style, onLayout, layouts }; const props = { style, onLayout, layouts };
return React.createElement(isOutside ? MenuOutside : renderer, props, optionsRenderer(options)); const optionsType = isOutside ? MenuOutside : renderer;
if (!isFunctional(optionsType)) {
props.ref = 'menuOptions';
}
return React.createElement(optionsType, props, optionsRenderer(options));
} }
_onLayout({ nativeEvent: { layout } }) { _onLayout({ nativeEvent: { layout } }) {
@ -202,3 +211,4 @@ MenuContext.childContextTypes = {
menuRegistry: React.PropTypes.object, menuRegistry: React.PropTypes.object,
menuActions: React.PropTypes.object, menuActions: React.PropTypes.object,
}; };

View File

@ -37,6 +37,7 @@ export const computePosition = ({ windowLayout, triggerLayout, optionsLayout })
return { top, left }; return { top, left };
}; };
const DURATION = 80;
export default class ContextMenu extends React.Component { export default class ContextMenu extends React.Component {
@ -45,15 +46,25 @@ export default class ContextMenu extends React.Component {
this.state = { this.state = {
scaleAnim: new Animated.Value(0.1), scaleAnim: new Animated.Value(0.1),
}; };
this.close = this.close.bind(this);
} }
componentDidMount() { componentDidMount() {
Animated.timing(this.state.scaleAnim, { Animated.timing(this.state.scaleAnim, {
duration: 80, duration: DURATION,
toValue: 1 toValue: 1
}).start(); }).start();
} }
close() {
return new Promise(resolve => {
Animated.timing(this.state.scaleAnim, {
duration: DURATION,
toValue: 0
}).start(resolve);
});
}
render() { render() {
const { style, children, layouts, ...other } = this.props; const { style, children, layouts, ...other } = this.props;
const animation = { const animation = {

View File

@ -9,6 +9,8 @@ export const computePosition = ({ windowLayout, optionsLayout }) => {
return { top, left }; return { top, left };
} }
const DURATION = 100;
export default class SlideInMenu extends React.Component { export default class SlideInMenu extends React.Component {
constructor(props) { constructor(props) {
@ -16,15 +18,25 @@ export default class SlideInMenu extends React.Component {
this.state = { this.state = {
slide: new Animated.Value(0), slide: new Animated.Value(0),
}; };
this.close = this.close.bind(this);
} }
componentDidMount() { componentDidMount() {
Animated.timing(this.state.slide, { Animated.timing(this.state.slide, {
duration: 100, duration: DURATION,
toValue: 1 toValue: 1
}).start(); }).start();
} }
close() {
return new Promise(resolve => {
Animated.timing(this.state.slide, {
duration: DURATION,
toValue: 0
}).start(resolve);
});
}
render() { render() {
const { style, children, layouts, ...other } = this.props; const { style, children, layouts, ...other } = this.props;
const { height: oHeight } = layouts.optionsLayout; const { height: oHeight } = layouts.optionsLayout;