Skip to content

Swipeable drawer add open actions #798

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 3 commits into from
Jun 7, 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
119 changes: 115 additions & 4 deletions demo/src/screens/componentScreens/DrawerScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class DrawerScreen extends Component {
this.state = {
hideItem: false,
showRightItems: true,
fullSwipeRight: true,
showLeftItem: true,
fullSwipeLeft: true
};
Expand All @@ -33,8 +34,28 @@ class DrawerScreen extends Component {
}
}

onFullSwipeRight = () => {

setTimeout(() => {
LayoutAnimation.configureNext({
update: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.scaleY
},
delete: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.scaleY,
duration: 2000
},
duration: 120
});
this.setState({hideItem: true});
}, 200);
};


onWillFullSwipeLeft = () => {

// TODO: consider including this functionality as part of the drawer component
setTimeout(() => {
LayoutAnimation.configureNext({
Expand All @@ -53,6 +74,78 @@ class DrawerScreen extends Component {
}, 200);
};

showItem = () => {
this.setState({hideItem: false});
};

openLeftDrawer = () => {
if (this.ref) {
this.ref.openLeft();
}
};
openLeftDrawerFull = () => {
if (this.ref) {
this.ref.openLeftFull();
}
};
openRightDrawer = () => {
if (this.ref) {
this.ref.openRight();
}
};
openRightDrawerFull = () => {
if (this.ref) {
this.ref.openRightFull();
}
};
closeDrawer = () => {
if (this.ref) {
this.ref.closeDrawer();
}
};

renderActions() {
return (
<View center>
<Text style={{fontSize: 20}}>Actions</Text>
<View row>
<Button
onPress={this.openLeftDrawer}
label="Open left"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.closeDrawer}
label="Close"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openRightDrawer}
label="Open right"
style={{margin: 3}}
size={'xSmall'}
/>
</View>
<View row>
<Button
onPress={this.openLeftDrawerFull}
label="Open left full"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openRightDrawerFull}
label="Open right full"
style={{margin: 3}}
size={'xSmall'}
/>
</View>
</View>
);
}

renderListItem() {
return (
<View bg-grey80 paddingH-20 paddingV-10 row centerV style={{borderBottomWidth: 1, borderColor: Colors.grey60}}>
Expand All @@ -70,6 +163,7 @@ class DrawerScreen extends Component {
render() {
const {
showRightItems,
fullSwipeRight,
showLeftItem,
fullSwipeLeft,
itemsTintColor,
Expand All @@ -82,6 +176,9 @@ class DrawerScreen extends Component {
itemsTintColor,
itemsIconSize,
bounciness,
ref: (component) => (this.ref = component),
fullSwipeRight,
onFullSwipeRight: this.onFullSwipeRight,
fullSwipeLeft,
onWillFullSwipeLeft: this.onWillFullSwipeLeft
};
Expand All @@ -101,14 +198,28 @@ class DrawerScreen extends Component {
</Text>
</View>
{!hideItem && (
<Drawer key={Date.now()} {...drawerProps}>
{this.renderListItem()}
</Drawer>
<>
<Drawer key={Date.now()} {...drawerProps}>
{this.renderListItem()}
</Drawer>
{this.renderActions()}
</>
)}
{hideItem && (
<View center>
<Button
round
onPress={this.showItem}
backgroundColor="#eeeeee"
iconSource={require('../../assets/icons/plus.png')}
/>
</View>
)}

<ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>
<View padding-20>
{renderBooleanOption.call(this, 'rightItems', 'showRightItems')}
{showRightItems && renderBooleanOption.call(this, 'fullSwipeRight', 'fullSwipeRight')}
{renderBooleanOption.call(this, 'leftItem', 'showLeftItem')}
{showLeftItem && renderBooleanOption.call(this, 'fullSwipeLeft', 'fullSwipeLeft')}
{renderColorOption.call(this, 'icon+text color', 'itemsTintColor')}
Expand Down
31 changes: 27 additions & 4 deletions src/components/drawer/Swipeable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export type PropType = {
rightThreshold?: number,
fullLeftThreshold?: number,
fullSwipeLeft?: boolean,
fullRightThreshold?: number,
fullSwipeRight?: boolean,
overshootLeft?: boolean,
overshootRight?: boolean,
overshootFriction?: number,
Expand All @@ -42,6 +44,8 @@ export type PropType = {
onSwipeableWillClose?: Function,
onFullSwipeLeft?: Function,
onWillFullSwipeLeft?: Function,
onFullSwipeRight?: Function,
onWillFullSwipeRight?: Function,
onDragStart?: Function,
renderLeftActions?: (progressAnimatedValue: any, dragAnimatedValue: any) => any,
renderRightActions?: (progressAnimatedValue: any, dragAnimatedValue: any) => any,
Expand All @@ -65,7 +69,8 @@ export default class Swipeable extends Component<PropType, StateType> {
friction: 1,
overshootFriction: 1,
useNativeAnimations: false, // issue in iPhone5
fullLeftThreshold: 0.45
fullLeftThreshold: 0.45,
fullRightThreshold: 0.45
};

// _onGestureEvent: ?Animated.Event;
Expand All @@ -79,7 +84,7 @@ export default class Swipeable extends Component<PropType, StateType> {
super(props);

const dragX = new Animated.Value(0);
// 0 -> open from either left/right,
// 0 -> open from either left/right,
// 1 -> closing to the left
// -1 -> closing to the right
this.rowState = 0;
Expand Down Expand Up @@ -192,7 +197,7 @@ export default class Swipeable extends Component<PropType, StateType> {
const {leftWidth = 0, rowWidth = 0} = this.state;
const {rightOffset = rowWidth} = this.state;
const rightWidth = rowWidth - rightOffset;
const {fullSwipeLeft, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold} = this.props;
const {fullSwipeLeft, fullSwipeRight, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold, fullRightThreshold} = this.props;

const startOffsetX = this._currentOffset() + dragX / friction;
const translationX = (dragX + DRAG_TOSS * velocityX) / friction;
Expand All @@ -201,6 +206,8 @@ export default class Swipeable extends Component<PropType, StateType> {
if (this.rowState === 0) {
if (fullSwipeLeft && translationX > rowWidth * fullLeftThreshold) {
toValue = rowWidth;
} else if (fullSwipeRight && translationX < -rowWidth * fullRightThreshold) {
toValue = -rowWidth;
} else if (translationX > leftThreshold) {
toValue = leftWidth;
} else if (translationX < -rightThreshold) {
Expand Down Expand Up @@ -235,7 +242,9 @@ export default class Swipeable extends Component<PropType, StateType> {
onSwipeableWillClose,
onSwipeableWillOpen,
onFullSwipeLeft,
onWillFullSwipeLeft
onWillFullSwipeLeft,
onFullSwipeRight,
onWillFullSwipeRight
} = this.props;

dragX.setValue(0);
Expand All @@ -254,6 +263,8 @@ export default class Swipeable extends Component<PropType, StateType> {
if (finished) {
if (toValue === rowWidth && onFullSwipeLeft) {
onFullSwipeLeft();
} else if (toValue === -rowWidth && onFullSwipeRight) {
onFullSwipeRight();
} else if (toValue > 0 && onSwipeableLeftOpen) {
onSwipeableLeftOpen();
} else if (toValue < 0 && onSwipeableRightOpen) {
Expand All @@ -270,6 +281,8 @@ export default class Swipeable extends Component<PropType, StateType> {

if (toValue === rowWidth && onWillFullSwipeLeft) {
onWillFullSwipeLeft()
} else if (toValue === -rowWidth && onWillFullSwipeRight) {
onWillFullSwipeRight()
} else if (toValue > 0 && onSwipeableLeftWillOpen) {
onSwipeableLeftWillOpen();
} else if (toValue < 0 && onSwipeableRightWillOpen) {
Expand Down Expand Up @@ -305,13 +318,23 @@ export default class Swipeable extends Component<PropType, StateType> {
this._animateRow(this._currentOffset(), leftWidth);
};

openLeftFull = () => {
const {rowWidth} = this.state;
this._animateRow(this._currentOffset(), rowWidth);
};

openRight = () => {
const {rowWidth = 0} = this.state;
const {rightOffset = rowWidth} = this.state;
const rightWidth = rowWidth - rightOffset;
this._animateRow(this._currentOffset(), -rightWidth);
};

openRightFull = () => {
const {rowWidth} = this.state;
this._animateRow(this._currentOffset(), -rowWidth);
};

_onRowLayout = ({nativeEvent}) => this.handleMeasure('rowWidth', nativeEvent);
_onLeftLayout = ({nativeEvent}) => this.handleMeasure('leftWidth', nativeEvent);
_onRightLayout = ({nativeEvent}) => this.handleMeasure('rightOffset', nativeEvent);
Expand Down
35 changes: 33 additions & 2 deletions src/components/drawer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,23 @@ class NewDrawer extends PureBaseComponent {
/**
* Callback for just before left item full swipe
*/
onWillFullSwipeLeft: PropTypes.func
onWillFullSwipeLeft: PropTypes.func,
/**
* Whether to allow a full right swipe
*/
fullSwipeRight: PropTypes.bool,
/**
* Threshold for a right full swipe (0-1)
*/
fullRightThreshold: PropTypes.number,
/**
* Callback for right item full swipe
*/
onFullSwipeRight: PropTypes.func,
/**
* Callback for just before right item full swipe
*/
onWillFullSwipeRight: PropTypes.func
};

static defaultProps = {
Expand Down Expand Up @@ -123,6 +139,22 @@ class NewDrawer extends PureBaseComponent {
this._swipeableRow.current.close();
};

openLeft = () => {
this._swipeableRow.current.openLeft();
};

openLeftFull = () => {
this._swipeableRow.current.openLeftFull();
};

openRight = () => {
this._swipeableRow.current.openRight();
};

openRightFull = () => {
this._swipeableRow.current.openRightFull();
};

/** Events */

onActionPress = (item) => {
Expand All @@ -139,7 +171,6 @@ class NewDrawer extends PureBaseComponent {
onSwipeableWillClose = () => {
_.invoke(this.props, 'onSwipeableWillClose', this.props);
};

/** Accessability */

getAccessibilityActions(withOnPress = false) {
Expand Down