Skip to content

Commit 95aa2c3

Browse files
authored
Swipeable drawer add open actions (#798)
* add open actions * Open Drawer to the right when user swipe over the threshold * add full swipe right and actions to demoApp
1 parent ca39973 commit 95aa2c3

File tree

3 files changed

+175
-10
lines changed

3 files changed

+175
-10
lines changed

demo/src/screens/componentScreens/DrawerScreen.js

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DrawerScreen extends Component {
2020
this.state = {
2121
hideItem: false,
2222
showRightItems: true,
23+
fullSwipeRight: true,
2324
showLeftItem: true,
2425
fullSwipeLeft: true
2526
};
@@ -33,8 +34,28 @@ class DrawerScreen extends Component {
3334
}
3435
}
3536

37+
onFullSwipeRight = () => {
38+
39+
setTimeout(() => {
40+
LayoutAnimation.configureNext({
41+
update: {
42+
type: LayoutAnimation.Types.easeInEaseOut,
43+
property: LayoutAnimation.Properties.scaleY
44+
},
45+
delete: {
46+
type: LayoutAnimation.Types.easeInEaseOut,
47+
property: LayoutAnimation.Properties.scaleY,
48+
duration: 2000
49+
},
50+
duration: 120
51+
});
52+
this.setState({hideItem: true});
53+
}, 200);
54+
};
55+
56+
3657
onWillFullSwipeLeft = () => {
37-
58+
3859
// TODO: consider including this functionality as part of the drawer component
3960
setTimeout(() => {
4061
LayoutAnimation.configureNext({
@@ -53,6 +74,78 @@ class DrawerScreen extends Component {
5374
}, 200);
5475
};
5576

77+
showItem = () => {
78+
this.setState({hideItem: false});
79+
};
80+
81+
openLeftDrawer = () => {
82+
if (this.ref) {
83+
this.ref.openLeft();
84+
}
85+
};
86+
openLeftDrawerFull = () => {
87+
if (this.ref) {
88+
this.ref.openLeftFull();
89+
}
90+
};
91+
openRightDrawer = () => {
92+
if (this.ref) {
93+
this.ref.openRight();
94+
}
95+
};
96+
openRightDrawerFull = () => {
97+
if (this.ref) {
98+
this.ref.openRightFull();
99+
}
100+
};
101+
closeDrawer = () => {
102+
if (this.ref) {
103+
this.ref.closeDrawer();
104+
}
105+
};
106+
107+
renderActions() {
108+
return (
109+
<View center>
110+
<Text style={{fontSize: 20}}>Actions</Text>
111+
<View row>
112+
<Button
113+
onPress={this.openLeftDrawer}
114+
label="Open left"
115+
style={{margin: 3}}
116+
size={'xSmall'}
117+
/>
118+
<Button
119+
onPress={this.closeDrawer}
120+
label="Close"
121+
style={{margin: 3}}
122+
size={'xSmall'}
123+
/>
124+
<Button
125+
onPress={this.openRightDrawer}
126+
label="Open right"
127+
style={{margin: 3}}
128+
size={'xSmall'}
129+
/>
130+
</View>
131+
<View row>
132+
<Button
133+
onPress={this.openLeftDrawerFull}
134+
label="Open left full"
135+
style={{margin: 3}}
136+
size={'xSmall'}
137+
/>
138+
<Button
139+
onPress={this.openRightDrawerFull}
140+
label="Open right full"
141+
style={{margin: 3}}
142+
size={'xSmall'}
143+
/>
144+
</View>
145+
</View>
146+
);
147+
}
148+
56149
renderListItem() {
57150
return (
58151
<View bg-grey80 paddingH-20 paddingV-10 row centerV style={{borderBottomWidth: 1, borderColor: Colors.grey60}}>
@@ -70,6 +163,7 @@ class DrawerScreen extends Component {
70163
render() {
71164
const {
72165
showRightItems,
166+
fullSwipeRight,
73167
showLeftItem,
74168
fullSwipeLeft,
75169
itemsTintColor,
@@ -82,6 +176,9 @@ class DrawerScreen extends Component {
82176
itemsTintColor,
83177
itemsIconSize,
84178
bounciness,
179+
ref: (component) => (this.ref = component),
180+
fullSwipeRight,
181+
onFullSwipeRight: this.onFullSwipeRight,
85182
fullSwipeLeft,
86183
onWillFullSwipeLeft: this.onWillFullSwipeLeft
87184
};
@@ -101,14 +198,28 @@ class DrawerScreen extends Component {
101198
</Text>
102199
</View>
103200
{!hideItem && (
104-
<Drawer key={Date.now()} {...drawerProps}>
105-
{this.renderListItem()}
106-
</Drawer>
201+
<>
202+
<Drawer key={Date.now()} {...drawerProps}>
203+
{this.renderListItem()}
204+
</Drawer>
205+
{this.renderActions()}
206+
</>
207+
)}
208+
{hideItem && (
209+
<View center>
210+
<Button
211+
round
212+
onPress={this.showItem}
213+
backgroundColor="#eeeeee"
214+
iconSource={require('../../assets/icons/plus.png')}
215+
/>
216+
</View>
107217
)}
108218

109219
<ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>
110220
<View padding-20>
111221
{renderBooleanOption.call(this, 'rightItems', 'showRightItems')}
222+
{showRightItems && renderBooleanOption.call(this, 'fullSwipeRight', 'fullSwipeRight')}
112223
{renderBooleanOption.call(this, 'leftItem', 'showLeftItem')}
113224
{showLeftItem && renderBooleanOption.call(this, 'fullSwipeLeft', 'fullSwipeLeft')}
114225
{renderColorOption.call(this, 'icon+text color', 'itemsTintColor')}

src/components/drawer/Swipeable.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export type PropType = {
2929
rightThreshold?: number,
3030
fullLeftThreshold?: number,
3131
fullSwipeLeft?: boolean,
32+
fullRightThreshold?: number,
33+
fullSwipeRight?: boolean,
3234
overshootLeft?: boolean,
3335
overshootRight?: boolean,
3436
overshootFriction?: number,
@@ -42,6 +44,8 @@ export type PropType = {
4244
onSwipeableWillClose?: Function,
4345
onFullSwipeLeft?: Function,
4446
onWillFullSwipeLeft?: Function,
47+
onFullSwipeRight?: Function,
48+
onWillFullSwipeRight?: Function,
4549
onDragStart?: Function,
4650
renderLeftActions?: (progressAnimatedValue: any, dragAnimatedValue: any) => any,
4751
renderRightActions?: (progressAnimatedValue: any, dragAnimatedValue: any) => any,
@@ -65,7 +69,8 @@ export default class Swipeable extends Component<PropType, StateType> {
6569
friction: 1,
6670
overshootFriction: 1,
6771
useNativeAnimations: false, // issue in iPhone5
68-
fullLeftThreshold: 0.45
72+
fullLeftThreshold: 0.45,
73+
fullRightThreshold: 0.45
6974
};
7075

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

8186
const dragX = new Animated.Value(0);
82-
// 0 -> open from either left/right,
87+
// 0 -> open from either left/right,
8388
// 1 -> closing to the left
8489
// -1 -> closing to the right
8590
this.rowState = 0;
@@ -192,7 +197,7 @@ export default class Swipeable extends Component<PropType, StateType> {
192197
const {leftWidth = 0, rowWidth = 0} = this.state;
193198
const {rightOffset = rowWidth} = this.state;
194199
const rightWidth = rowWidth - rightOffset;
195-
const {fullSwipeLeft, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold} = this.props;
200+
const {fullSwipeLeft, fullSwipeRight, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold, fullRightThreshold} = this.props;
196201

197202
const startOffsetX = this._currentOffset() + dragX / friction;
198203
const translationX = (dragX + DRAG_TOSS * velocityX) / friction;
@@ -201,6 +206,8 @@ export default class Swipeable extends Component<PropType, StateType> {
201206
if (this.rowState === 0) {
202207
if (fullSwipeLeft && translationX > rowWidth * fullLeftThreshold) {
203208
toValue = rowWidth;
209+
} else if (fullSwipeRight && translationX < -rowWidth * fullRightThreshold) {
210+
toValue = -rowWidth;
204211
} else if (translationX > leftThreshold) {
205212
toValue = leftWidth;
206213
} else if (translationX < -rightThreshold) {
@@ -235,7 +242,9 @@ export default class Swipeable extends Component<PropType, StateType> {
235242
onSwipeableWillClose,
236243
onSwipeableWillOpen,
237244
onFullSwipeLeft,
238-
onWillFullSwipeLeft
245+
onWillFullSwipeLeft,
246+
onFullSwipeRight,
247+
onWillFullSwipeRight
239248
} = this.props;
240249

241250
dragX.setValue(0);
@@ -254,6 +263,8 @@ export default class Swipeable extends Component<PropType, StateType> {
254263
if (finished) {
255264
if (toValue === rowWidth && onFullSwipeLeft) {
256265
onFullSwipeLeft();
266+
} else if (toValue === -rowWidth && onFullSwipeRight) {
267+
onFullSwipeRight();
257268
} else if (toValue > 0 && onSwipeableLeftOpen) {
258269
onSwipeableLeftOpen();
259270
} else if (toValue < 0 && onSwipeableRightOpen) {
@@ -270,6 +281,8 @@ export default class Swipeable extends Component<PropType, StateType> {
270281

271282
if (toValue === rowWidth && onWillFullSwipeLeft) {
272283
onWillFullSwipeLeft()
284+
} else if (toValue === -rowWidth && onWillFullSwipeRight) {
285+
onWillFullSwipeRight()
273286
} else if (toValue > 0 && onSwipeableLeftWillOpen) {
274287
onSwipeableLeftWillOpen();
275288
} else if (toValue < 0 && onSwipeableRightWillOpen) {
@@ -305,13 +318,23 @@ export default class Swipeable extends Component<PropType, StateType> {
305318
this._animateRow(this._currentOffset(), leftWidth);
306319
};
307320

321+
openLeftFull = () => {
322+
const {rowWidth} = this.state;
323+
this._animateRow(this._currentOffset(), rowWidth);
324+
};
325+
308326
openRight = () => {
309327
const {rowWidth = 0} = this.state;
310328
const {rightOffset = rowWidth} = this.state;
311329
const rightWidth = rowWidth - rightOffset;
312330
this._animateRow(this._currentOffset(), -rightWidth);
313331
};
314332

333+
openRightFull = () => {
334+
const {rowWidth} = this.state;
335+
this._animateRow(this._currentOffset(), -rowWidth);
336+
};
337+
315338
_onRowLayout = ({nativeEvent}) => this.handleMeasure('rowWidth', nativeEvent);
316339
_onLeftLayout = ({nativeEvent}) => this.handleMeasure('leftWidth', nativeEvent);
317340
_onRightLayout = ({nativeEvent}) => this.handleMeasure('rightOffset', nativeEvent);

src/components/drawer/index.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,23 @@ class NewDrawer extends PureBaseComponent {
8383
/**
8484
* Callback for just before left item full swipe
8585
*/
86-
onWillFullSwipeLeft: PropTypes.func
86+
onWillFullSwipeLeft: PropTypes.func,
87+
/**
88+
* Whether to allow a full right swipe
89+
*/
90+
fullSwipeRight: PropTypes.bool,
91+
/**
92+
* Threshold for a right full swipe (0-1)
93+
*/
94+
fullRightThreshold: PropTypes.number,
95+
/**
96+
* Callback for right item full swipe
97+
*/
98+
onFullSwipeRight: PropTypes.func,
99+
/**
100+
* Callback for just before right item full swipe
101+
*/
102+
onWillFullSwipeRight: PropTypes.func
87103
};
88104

89105
static defaultProps = {
@@ -123,6 +139,22 @@ class NewDrawer extends PureBaseComponent {
123139
this._swipeableRow.current.close();
124140
};
125141

142+
openLeft = () => {
143+
this._swipeableRow.current.openLeft();
144+
};
145+
146+
openLeftFull = () => {
147+
this._swipeableRow.current.openLeftFull();
148+
};
149+
150+
openRight = () => {
151+
this._swipeableRow.current.openRight();
152+
};
153+
154+
openRightFull = () => {
155+
this._swipeableRow.current.openRightFull();
156+
};
157+
126158
/** Events */
127159

128160
onActionPress = (item) => {
@@ -139,7 +171,6 @@ class NewDrawer extends PureBaseComponent {
139171
onSwipeableWillClose = () => {
140172
_.invoke(this.props, 'onSwipeableWillClose', this.props);
141173
};
142-
143174
/** Accessability */
144175

145176
getAccessibilityActions(withOnPress = false) {

0 commit comments

Comments
 (0)