From 1aa35a3d2a412bd286dcb5714774fb82e67331d5 Mon Sep 17 00:00:00 2001 From: bolencki13 Date: Sat, 30 Apr 2016 22:28:08 -0400 Subject: [PATCH 1/2] 3D touch support --- GHContextMenu/GHContextMenuView.h | 12 ++++ GHContextMenu/GHContextMenuView.m | 91 +++++++++++++++++++++++++++++++ README.md | 9 +++ 3 files changed, 112 insertions(+) diff --git a/GHContextMenu/GHContextMenuView.h b/GHContextMenu/GHContextMenuView.h index 51975b6..4afe3d1 100644 --- a/GHContextMenu/GHContextMenuView.h +++ b/GHContextMenu/GHContextMenuView.h @@ -26,6 +26,7 @@ typedef NS_ENUM(NSInteger, GHContextMenuActionType){ @property (nonatomic, assign) GHContextMenuActionType menuActionType; - (void) longPressDetected:(UIGestureRecognizer*) gestureRecognizer; +- (void) deepPressDetected:(UIGestureRecognizer*) gestureRecognizer; @end @@ -45,3 +46,14 @@ typedef NS_ENUM(NSInteger, GHContextMenuActionType){ - (void) didSelectItemAtIndex:(NSInteger) selectedIndex forMenuAtPoint:(CGPoint) point; @end + + +/* + * 3D touch GestureRecognizer + */ +@interface DeepGestureRecognizer : UIGestureRecognizer +@property (nonatomic, readonly) CGFloat threshold; +@property (nonatomic) BOOL vibrateOn3DPress; +@property (nonatomic) BOOL dragMode; +- (instancetype)initWithTarget:(id)target action:(SEL)action threshold:(CGFloat)threshold; +@end diff --git a/GHContextMenu/GHContextMenuView.m b/GHContextMenu/GHContextMenuView.m index bf7c93a..62b0379 100644 --- a/GHContextMenu/GHContextMenuView.m +++ b/GHContextMenu/GHContextMenuView.m @@ -178,6 +178,40 @@ - (void) longPressDetected:(UIGestureRecognizer*) gestureRecognizer } } +- (void)deepPressDetected:(UIGestureRecognizer*) gestureRecognizer +{ + if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { + self.frame = [UIScreen mainScreen].bounds; + self.prevIndex = -1; + + CGPoint pointInView = [gestureRecognizer locationInView:gestureRecognizer.view]; + if (self.dataSource != nil && [self.dataSource respondsToSelector:@selector(shouldShowMenuAtPoint:)] && ![self.dataSource shouldShowMenuAtPoint:pointInView]){ + return; + } + + [[UIApplication sharedApplication].keyWindow addSubview:self]; + self.longPressLocation = [gestureRecognizer locationInView:self]; + + self.layer.backgroundColor = [UIColor colorWithWhite:0.1f alpha:.8f].CGColor; + self.isShowing = YES; + [self animateMenu:YES]; + [self setNeedsDisplay]; + } + + if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { + if (self.isShowing && self.menuActionType == GHContextMenuActionTypePan) { + self.isPaning = YES; + self.curretnLocation = [gestureRecognizer locationInView:self]; + } + } + + // Only trigger if we're using the GHContextMenuActionTypePan (default) + if(gestureRecognizer.state == UIGestureRecognizerStateEnded && self.menuActionType == GHContextMenuActionTypePan ) { + CGPoint menuAtPoint = [self convertPoint:self.longPressLocation toView:gestureRecognizer.view]; + [self dismissWithSelectedIndexForMenuAtPoint:menuAtPoint]; + } +} + - (void) showMenu { @@ -487,3 +521,60 @@ - (void)drawRect:(CGRect)rect } } @end + + +/* + * 3D touch GestureRecognizer + */ +#import +#import + +@interface DeepGestureRecognizer () { + BOOL is3DPress; +} + +@end + +@implementation DeepGestureRecognizer +- (instancetype)initWithTarget:(id)target action:(SEL)action threshold:(CGFloat)threshold { + if (self == [super initWithTarget:target action:action]) { + _threshold = threshold; + _vibrateOn3DPress = YES; + _dragMode = YES; + is3DPress = NO; + } + return self; +} +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self handleTouch:[[touches allObjects] objectAtIndex:0]]; +} +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self handleTouch:[[touches allObjects] objectAtIndex:0]]; +} +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesEnded:touches withEvent:event]; + if (_dragMode == YES) { + self.state = UIGestureRecognizerStateEnded; + } else { + self.state = (is3DPress ? UIGestureRecognizerStateEnded : UIGestureRecognizerStateFailed); + } + is3DPress = NO; +} +- (void)handleTouch:(UITouch*)touch { + // if (touch.force != 0 && touch.maximumPossibleForce != 0) { + // return; + // } + if (!is3DPress && (touch.force/touch.maximumPossibleForce) >= _threshold) { + + if (_vibrateOn3DPress == YES) { + AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); + } + + self.state = UIGestureRecognizerStateBegan; + is3DPress = YES; + } else if (is3DPress && (touch.force/touch.maximumPossibleForce) < _threshold && _dragMode == NO) { + self.state = UIGestureRecognizerStateEnded; + is3DPress = NO; + } +} +@end diff --git a/README.md b/README.md index 6ef172f..1cddee1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,15 @@ Sample app contains examples of how to add context menu for UIView and UICollect UILongPressGestureRecognizer* _longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:overlay action:@selector(longPressDetected:)]; [self.view addGestureRecognizer:_longPressRecognizer]; +// 3D touch + GHContextMenuView* overlay = [[GHContextMenuView alloc] init]; + overlay.dataSource = self; + overlay.delegate = self; + + DeepGestureRecognizer *_deepGestureRecognizer = [[DeepGestureRecognizer alloc] initWithTarget:overlay action:@selector(deepPressDetected:) threshold:1.0]; + [self.view addGestureRecognizer:_deepGestureRecognizer]; + + // Implementing data source methods - (NSInteger) numberOfMenuItems { From 9291a43da63ce7a4435c5f833927110a7a84621f Mon Sep 17 00:00:00 2001 From: bolencki13 Date: Sat, 30 Apr 2016 22:37:56 -0400 Subject: [PATCH 2/2] Removed Redundancies --- GHContextMenu/GHContextMenuView.m | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/GHContextMenu/GHContextMenuView.m b/GHContextMenu/GHContextMenuView.m index 62b0379..33e91c4 100644 --- a/GHContextMenu/GHContextMenuView.m +++ b/GHContextMenu/GHContextMenuView.m @@ -180,36 +180,7 @@ - (void) longPressDetected:(UIGestureRecognizer*) gestureRecognizer - (void)deepPressDetected:(UIGestureRecognizer*) gestureRecognizer { - if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { - self.frame = [UIScreen mainScreen].bounds; - self.prevIndex = -1; - - CGPoint pointInView = [gestureRecognizer locationInView:gestureRecognizer.view]; - if (self.dataSource != nil && [self.dataSource respondsToSelector:@selector(shouldShowMenuAtPoint:)] && ![self.dataSource shouldShowMenuAtPoint:pointInView]){ - return; - } - - [[UIApplication sharedApplication].keyWindow addSubview:self]; - self.longPressLocation = [gestureRecognizer locationInView:self]; - - self.layer.backgroundColor = [UIColor colorWithWhite:0.1f alpha:.8f].CGColor; - self.isShowing = YES; - [self animateMenu:YES]; - [self setNeedsDisplay]; - } - - if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { - if (self.isShowing && self.menuActionType == GHContextMenuActionTypePan) { - self.isPaning = YES; - self.curretnLocation = [gestureRecognizer locationInView:self]; - } - } - - // Only trigger if we're using the GHContextMenuActionTypePan (default) - if(gestureRecognizer.state == UIGestureRecognizerStateEnded && self.menuActionType == GHContextMenuActionTypePan ) { - CGPoint menuAtPoint = [self convertPoint:self.longPressLocation toView:gestureRecognizer.view]; - [self dismissWithSelectedIndexForMenuAtPoint:menuAtPoint]; - } + [self longPressDetected:gestureRecognizer]; } - (void) showMenu