Skip to content

Fix/dialog animation #891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 16, 2020
Merged
8 changes: 8 additions & 0 deletions generatedTypes/components/dialog/OverlayFadingBackground.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference types="react" />
interface Props {
dialogVisibility: boolean;
modalVisibility: boolean;
overlayBackgroundColor: string;
}
declare const _default: ({ dialogVisibility, modalVisibility, overlayBackgroundColor }: Props) => JSX.Element;
export default _default;
38 changes: 10 additions & 28 deletions src/components/dialog/DialogDismissibleView.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ class DialogDismissibleView extends PureComponent {
this.setInitialValues();
this.state = {
visible: props.visible,
hide: false,
isAnimating: false
hide: false
};
}

Expand All @@ -54,22 +53,12 @@ class DialogDismissibleView extends PureComponent {
this.width = Constants.screenWidth;
this.height = Constants.screenHeight;
this.hiddenLocation = this.getHiddenLocation(0, 0);
this.animationStyle = {
transform: [
{
translateX: this.hiddenLocation.left
},
{
translateY: this.hiddenLocation.top
}
]
};
}

componentDidUpdate(prevProps) {
const {isPanning, dragDeltas, swipeDirections} = this.props.context; // eslint-disable-line
const {dragDeltas: prevDragDeltas, swipeDirections: prevSwipeDirections} = prevProps.context; // eslint-disable-line
const {hide, isAnimating} = this.state;
const {hide} = this.state;

if (
isPanning &&
Expand All @@ -87,7 +76,7 @@ class DialogDismissibleView extends PureComponent {
this.onSwipe(swipeDirections);
}

if (hide && !isAnimating) {
if (hide) {
this.hide();
}
}
Expand Down Expand Up @@ -126,10 +115,6 @@ class DialogDismissibleView extends PureComponent {
this.swipe = swipeDirections;
};

onAnimationEnd = () => {
this.setState({isAnimating: false});
};

getHiddenLocation = (left, top) => {
const {direction} = this.props;
const topInset = Constants.isIphoneX ? Constants.getSafeAreaInsets().top : Constants.isIOS ? 20 : 0;
Expand All @@ -156,14 +141,12 @@ class DialogDismissibleView extends PureComponent {
};

animateTo = (toValue, animationEndCallback) => {
const animation = Animated.timing(this.animatedValue, {
Animated.timing(this.animatedValue, {
toValue,
duration: 400,
easing: Easing.bezier(0.65, 0, 0.35, 1),
duration: 300,
easing: Easing.bezier(0.2, 0, 0.35, 1),
useNativeDriver: true
});

this.setState({isAnimating: true}, () => animation.start(animationEndCallback));
}).start(animationEndCallback);
};

getAnimationStyle = () => {
Expand Down Expand Up @@ -194,8 +177,7 @@ class DialogDismissibleView extends PureComponent {
this.thresholdY = this.height / 2;
this.ref.measureInWindow((x, y) => {
this.hiddenLocation = this.getHiddenLocation(x, y);
this.animationStyle = this.getAnimationStyle();
this.animateTo(1, this.onAnimationEnd);
this.animateTo(1);
});
};

Expand All @@ -210,7 +192,7 @@ class DialogDismissibleView extends PureComponent {
? 1 + left / this.hiddenLocation.left
: 1 + top / this.hiddenLocation.top;

this.animateTo(toValue, this.onAnimationEnd);
this.animateTo(toValue);
};

onPanLocationChanged = ({left, top}) => {
Expand Down Expand Up @@ -241,7 +223,7 @@ class DialogDismissibleView extends PureComponent {
<View ref={r => (this.ref = r)} style={containerStyle} onLayout={this.onLayout}>
<PanResponderView
// !visible && styles.hidden is done to fix a bug is iOS
style={[style, this.animationStyle, !visible && styles.hidden]}
style={[style, this.getAnimationStyle(), !visible && styles.hidden]}
isAnimated
onPanLocationChanged={this.onPanLocationChanged}
>
Expand Down
46 changes: 46 additions & 0 deletions src/components/dialog/OverlayFadingBackground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, {useRef, useEffect, useCallback, useMemo} from 'react';
import View from '../view';
import {Animated} from 'react-native';

interface Props {
dialogVisibility: boolean;
modalVisibility: boolean;
overlayBackgroundColor: string;
}

export default ({
dialogVisibility,
modalVisibility,
overlayBackgroundColor
}: Props) => {
const fadeAnimation = useRef(new Animated.Value(0)).current;

const animateFading = useCallback((toValue) => {
Animated.timing(fadeAnimation, {
toValue,
duration: 400,
useNativeDriver: true
}).start();
}, [fadeAnimation]);

useEffect(() => {
if (!dialogVisibility) {
animateFading(0);
}
}, [dialogVisibility, animateFading]);

useEffect(() => {
if (modalVisibility) {
animateFading(1);
}
}, [modalVisibility, animateFading]);

const style = useMemo(() => {
return {
opacity: fadeAnimation,
backgroundColor: overlayBackgroundColor
};
}, [overlayBackgroundColor, fadeAnimation]);

return <View absF animated style={style} pointerEvents="none"/>;
};
16 changes: 11 additions & 5 deletions src/components/dialog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Modal from '../modal';
import View from '../view';
import PanListenerView from '../panningViews/panListenerView';
import DialogDismissibleView from './DialogDismissibleView';
import OverlayFadingBackground from './OverlayFadingBackground';
import PanningProvider from '../panningViews/panningProvider';

// TODO: KNOWN ISSUES
Expand Down Expand Up @@ -155,7 +156,7 @@ class Dialog extends BaseComponent {
}
});
};

onModalDismissed = () => {
_.invoke(this.props, 'onDialogDismissed', this.props);
_.invoke(this.props, 'onModalDismissed', this.props);
Expand Down Expand Up @@ -199,7 +200,8 @@ class Dialog extends BaseComponent {

// TODO: renderOverlay {_.invoke(this.getThemeProps(), 'renderOverlay')}
renderDialogContainer = () => {
const {useSafeArea, bottom} = this.getThemeProps();
const {modalVisibility, dialogVisibility} = this.state;
const {useSafeArea, bottom, overlayBackgroundColor} = this.getThemeProps();
const addBottomSafeArea = Constants.isIphoneX && (useSafeArea && bottom);
const bottomInsets = Constants.getSafeAreaInsets().bottom - 8; // TODO: should this be here or in the input style?

Expand All @@ -209,6 +211,11 @@ class Dialog extends BaseComponent {
style={[this.styles.centerHorizontal, this.styles.alignments, this.styles.container]}
pointerEvents="box-none"
>
<OverlayFadingBackground
modalVisibility={modalVisibility}
dialogVisibility={dialogVisibility}
overlayBackgroundColor={overlayBackgroundColor}
/>
{this.renderDialogView()}
{addBottomSafeArea && <View style={{marginTop: bottomInsets}}/>}
</View>
Expand All @@ -217,17 +224,16 @@ class Dialog extends BaseComponent {

render = () => {
const {orientationKey, modalVisibility} = this.state;
const {overlayBackgroundColor, supportedOrientations, accessibilityLabel} = this.getThemeProps();
const {supportedOrientations, accessibilityLabel} = this.getThemeProps();

return (
<Modal
key={orientationKey}
transparent
visible={modalVisibility}
animationType={'fade'}
animationType={'none'}
onBackgroundPress={this.hideDialogView}
onRequestClose={this.hideDialogView}
overlayBackgroundColor={overlayBackgroundColor}
onDismiss={this.onModalDismissed}
supportedOrientations={supportedOrientations}
accessibilityLabel={accessibilityLabel}
Expand Down
6 changes: 2 additions & 4 deletions src/components/panningViews/panResponderView.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, {PureComponent} from 'react';
import {Animated} from 'react-native';
import View from '../view';
import asPanViewConsumer from './asPanViewConsumer';

Expand Down Expand Up @@ -89,12 +88,11 @@ class PanResponderView extends PureComponent {

render() {
const {isAnimated, ...others} = this.props;
const Container = isAnimated ? Animated.View : View;

return (
<Container ref={this.ref} pointerEvents={'box-none'} {...others}>
<View animated={isAnimated} ref={this.ref} pointerEvents={'box-none'} {...others}>
{this.props.children}
</Container>
</View>
);
}
}
Expand Down