Skip to content

Re-introduce PanDismissibleView #612

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 1 commit into from
Jan 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demo/src/screens/MenuStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const navigationData = {
{title: 'Hint', tags: 'hints tooltip', screen: 'unicorn.components.HintsScreen'},
{title: 'Overlays', tags: 'overlay image', screen: 'unicorn.components.OverlaysScreen'},
{title: 'Page Control', tags: 'page', screen: 'unicorn.components.PageControlScreen'},
{title: 'Pan Dismissible', tags: 'pan swipe drag dismiss', screen: 'unicorn.components.PanDismissibleScreen'},
{title: 'Pan Listener', tags: 'pan swipe drag listener', screen: 'unicorn.components.PanListenerScreen'},
{title: 'Pan Responder', tags: 'pan swipe drag responder', screen: 'unicorn.components.PanResponderScreen'},
{title: 'Shared Transition', tags: 'shared transition element', screen: 'unicorn.components.SharedTransitionScreen'},
Expand Down
112 changes: 112 additions & 0 deletions demo/src/screens/componentScreens/PanDismissibleScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, {Component} from 'react';
import {StyleSheet} from 'react-native';
import {
Button,
View,
Text,
Switch,
Colors,
Typography,
PanListenerView,
PanningProvider,
PanDismissibleView
} from 'react-native-ui-lib';

const PAN_LISTENER_VIEW_HEIGHT = 100;

export default class PanDismissibleScreen extends Component {
state = {
location: {left: 50, top: 50},
isCoupled: true,
key: false
};

switchExample = () => {
const {isCoupled, location} = this.state;
if (isCoupled) {
this.setState({
isCoupled: false,
location: {left: location.left, top: location.top - PAN_LISTENER_VIEW_HEIGHT}
});
} else {
this.setState({
isCoupled: true,
location: {left: location.left, top: location.top + PAN_LISTENER_VIEW_HEIGHT}
});
}
};

reset = () => {
this.setState({key: !this.state.key});
};

renderPanListener = () => {
return (
<PanListenerView style={styles.panListener}>
<Text style={styles.largeText}>Drag\Swipe here</Text>
</PanListenerView>
);
};

render() {
const {isCoupled, key} = this.state;
const panListener = this.renderPanListener();

return (
<View flex bg-dark80>
<Text style={styles.largeText}>Pan Dismissible</Text>
<View style={styles.container}>
<Switch value={isCoupled} onValueChange={this.switchExample} style={styles.switch}/>
<Text style={styles.smallText}>{isCoupled ? 'Coupled' : 'Uncoupled'}</Text>
</View>
<Button label="Reset" size={Button.sizes.medium} outline style={styles.button} onPress={this.reset}/>
<View centerH>
<PanningProvider>
{!isCoupled && panListener}
<PanDismissibleView
key={key}
style={[styles.panDismissible, {marginTop: isCoupled ? PAN_LISTENER_VIEW_HEIGHT : undefined}]}
>
{isCoupled && panListener}
</PanDismissibleView>
</PanningProvider>
</View>
</View>
);
}
}

const styles = StyleSheet.create({
largeText: {
...Typography.text50,
margin: 20
},
container: {
flexDirection: 'row',
marginBottom: 20,
alignSelf: 'center'
},
panDismissible: {
width: 250,
height: 250,
backgroundColor: Colors.blue30
},
panListener: {
width: '100%',
height: PAN_LISTENER_VIEW_HEIGHT,
backgroundColor: Colors.blue60,
justifyContent: 'center'
},
smallText: {
...Typography.text70,
marginLeft: 20
},
switch: {
marginLeft: 20,
alignSelf: 'center'
},
button: {
alignSelf: 'center',
marginBottom: 20
}
});
2 changes: 2 additions & 0 deletions demo/src/screens/componentScreens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import InputsScreen from './InputsScreen';
import MaskedInputScreen from './MaskedInputScreen';
import OverlaysScreen from './OverlaysScreen';
import PageControlScreen from './PageControlScreen';
import PanDismissibleScreen from './PanDismissibleScreen';
import PanListenerScreen from './PanListenerScreen';
import PanResponderScreen from './PanResponderScreen';
import PickerScreen from './PickerScreen';
Expand Down Expand Up @@ -54,6 +55,7 @@ Navigation.registerComponent('unicorn.components.InputsScreen', () => InputsScre
Navigation.registerComponent('unicorn.components.MaskedInputScreen', () => MaskedInputScreen);
Navigation.registerComponent('unicorn.components.OverlaysScreen', () => OverlaysScreen);
Navigation.registerComponent('unicorn.components.PageControlScreen', () => PageControlScreen);
Navigation.registerComponent('unicorn.components.PanDismissibleScreen', () => PanDismissibleScreen);
Navigation.registerComponent('unicorn.components.PanListenerScreen', () => PanListenerScreen);
Navigation.registerComponent('unicorn.components.PanResponderScreen', () => PanResponderScreen);
Navigation.registerComponent('unicorn.components.PickerScreen', () => PickerScreen);
Expand Down
1 change: 0 additions & 1 deletion src/components/panningViews/asPanViewConsumer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import PanningContext from './panningContext';

function asPanViewConsumer(WrappedComponent) {
class PanViewConsumer extends Component {
// TODO: remove when removing PanDismissibleView
saveRef = r => {
this.contentRef = r;
};
Expand Down
42 changes: 35 additions & 7 deletions src/components/panningViews/panDismissibleView.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ class PanDismissibleView extends PureComponent {
speed: PropTypes.number,
bounciness: PropTypes.number,
duration: PropTypes.number
})
}),
/**
* Allow diagonal dismiss, this is false by default,
* since it looks better and most cases.
*/
allowDiagonalDismiss: PropTypes.bool
};

static defaultProps = {
Expand All @@ -54,7 +59,8 @@ class PanDismissibleView extends PureComponent {
bounciness: DEFAULT_BOUNCINESS,
duration: DEFAULT_DISMISS_ANIMATION_DURATION
},
onDismiss: _.noop
onDismiss: _.noop,
allowDiagonalDismiss: false
};

constructor(props) {
Expand Down Expand Up @@ -209,13 +215,24 @@ class PanDismissibleView extends PureComponent {
};

getDismissAnimationDirection = () => {
const {swipeDirections, dragDirections} = this.props.context; // eslint-disable-line
const {allowDiagonalDismiss} = this.props;
const {swipeDirections, swipeVelocities, dragDirections, dragDeltas} = this.props.context; // eslint-disable-line
const hasHorizontalSwipe = !_.isUndefined(swipeDirections.x);
const hasVerticalSwipe = !_.isUndefined(swipeDirections.y);
let isRight;
let isDown;

if (hasHorizontalSwipe || hasVerticalSwipe) {
if (!allowDiagonalDismiss && hasHorizontalSwipe && hasVerticalSwipe) {
if (Math.abs(swipeVelocities.y) > Math.abs(swipeVelocities.x)) {
isDown = swipeDirections.y === PanningProvider.Directions.DOWN;
} else {
isRight = swipeDirections.x === PanningProvider.Directions.RIGHT;
}

return {isRight, isDown};
}

if (hasHorizontalSwipe) {
isRight = swipeDirections.x === PanningProvider.Directions.RIGHT;
}
Expand All @@ -225,11 +242,23 @@ class PanDismissibleView extends PureComponent {
}
} else {
// got here from a drag beyond threshold
if (!_.isUndefined(dragDirections.x)) {
const hasHorizontalDrag = !_.isUndefined(dragDirections.x);
const hasVerticalDrag = !_.isUndefined(dragDirections.y);
if (!allowDiagonalDismiss && hasHorizontalDrag && hasVerticalDrag) {
if (Math.abs(dragDeltas.y) > Math.abs(dragDeltas.x)) {
isDown = dragDirections.y === PanningProvider.Directions.DOWN;
} else {
isRight = dragDirections.x === PanningProvider.Directions.RIGHT;
}

return {isRight, isDown};
}

if (hasHorizontalDrag) {
isRight = dragDirections.x === PanningProvider.Directions.RIGHT;
}

if (!_.isUndefined(dragDirections.y)) {
if (hasVerticalDrag) {
isDown = dragDirections.y === PanningProvider.Directions.DOWN;
}
}
Expand Down Expand Up @@ -296,8 +325,7 @@ class PanDismissibleView extends PureComponent {

onDismissAnimationFinished = ({finished}) => {
if (finished) {
const {onDismiss} = this.props;
onDismiss();
_.invoke(this.props, 'onDismiss');
}
};

Expand Down
10 changes: 8 additions & 2 deletions src/components/panningViews/panListenerView.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ class PanListenerView extends PureBaseComponent {
* The sensitivity beyond which a pan is no longer considered a drag, but a swipe (default is 1.8)
* Note: a pan would have to occur (i.e. the panSensitivity has already been surpassed)
*/
swipeVelocitySensitivity: PropTypes.number
swipeVelocitySensitivity: PropTypes.number,
/**
* Is there a view that is clickable (has onPress etc.) in the PanListenerView.
* This can affect the panability of this component.
*/
isClickable: PropTypes.bool
};

static defaultProps = {
Expand All @@ -81,8 +86,9 @@ class PanListenerView extends PureBaseComponent {

this.state = {};

const {isClickable} = props;
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: this.yes,
onStartShouldSetPanResponder: isClickable ? this.shouldPan : this.yes,
onMoveShouldSetPanResponder: this.shouldPan,
onStartShouldSetPanResponderCapture: this.no,
onMoveShouldSetPanResponderCapture: this.no,
Expand Down