From 72b65665a47f79720577e1a95cbeba20345caf38 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 00:19:51 -0400 Subject: [PATCH 1/8] Fix singular matrix error and reset center of view --- MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index edfb90c..574ef86 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -39,13 +39,15 @@ - (void)mdc_swipeToChooseSetup:(MDCSwipeOptions *)options { self.mdc_options = options ? options : [MDCSwipeOptions new]; self.mdc_viewState = [MDCViewState new]; self.mdc_viewState.originalCenter = self.center; - self.mdc_viewState.originalTransform = self.layer.transform; + self.mdc_viewState.originalTransform = CATransform3DMakeAffineTransform(CGAffineTransformMake(1, 0, 0, 1, 0, 0)); [self mdc_setupPanGestureRecognizer]; } - (void)mdc_swipe:(MDCSwipeDirection)direction { [self mdc_swipeToChooseSetupIfNecessary]; + self.mdc_viewState.originalCenter = self.center; + // A swipe in no particular direction "finalizes" the swipe. if (direction == MDCSwipeDirectionNone) { From a765279d697089ddc9411e278906271e0078c8e7 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 01:00:37 -0400 Subject: [PATCH 2/8] First additions of vertical swiping --- MDCSwipeToChoose-prefix.pch | 5 + MDCSwipeToChoose.xcodeproj/project.pbxproj | 4 +- MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch | 2 +- .../Public/Options/MDCSwipeOptions.m | 2 +- .../Options/MDCSwipeToChooseViewOptions.h | 60 +++++++---- .../Options/MDCSwipeToChooseViewOptions.m | 18 ++-- .../Public/State/MDCSwipeDirection.h | 3 +- .../Public/Views/MDCSwipeToChooseView.h | 17 +-- .../Public/Views/MDCSwipeToChooseView.m | 101 ++++++++++++------ .../Public/Views/UIView+MDCSwipeToChoose.m | 19 ++-- 10 files changed, 154 insertions(+), 77 deletions(-) create mode 100644 MDCSwipeToChoose-prefix.pch diff --git a/MDCSwipeToChoose-prefix.pch b/MDCSwipeToChoose-prefix.pch new file mode 100644 index 0000000..95cf11d --- /dev/null +++ b/MDCSwipeToChoose-prefix.pch @@ -0,0 +1,5 @@ +#ifdef __OBJC__ +#import +#endif + +#import "Pods-environment.h" diff --git a/MDCSwipeToChoose.xcodeproj/project.pbxproj b/MDCSwipeToChoose.xcodeproj/project.pbxproj index 8617c72..6c81e7e 100644 --- a/MDCSwipeToChoose.xcodeproj/project.pbxproj +++ b/MDCSwipeToChoose.xcodeproj/project.pbxproj @@ -49,6 +49,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + A59B81FD1B2E8ED00074A4F3 /* MDCSwipeToChoose-prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MDCSwipeToChoose-prefix.pch"; sourceTree = ""; }; DA06338118F23C2B009EBE62 /* MDCGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCGeometry.h; sourceTree = ""; }; DA06338218F23C2B009EBE62 /* MDCGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDCGeometry.m; sourceTree = ""; }; DA0633B118F23EAD009EBE62 /* MDCSwipeToChoose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCSwipeToChoose.h; sourceTree = ""; }; @@ -69,7 +70,6 @@ DA0633D018F2F9E2009EBE62 /* MDCSwipeToChooseDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCSwipeToChooseDelegate.h; sourceTree = ""; }; DA5B73B318F2330B00BB5F8E /* libMDCSwipeToChoose.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMDCSwipeToChoose.a; sourceTree = BUILT_PRODUCTS_DIR; }; DA5B73B618F2330B00BB5F8E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - DA5B73BA18F2330B00BB5F8E /* MDCSwipeToChoose-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MDCSwipeToChoose-Prefix.pch"; sourceTree = ""; }; DA5B73C318F2330B00BB5F8E /* MDCSwipeToChooseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MDCSwipeToChooseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DA5B73C418F2330B00BB5F8E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; DA5B73C718F2330B00BB5F8E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; @@ -207,7 +207,7 @@ DA5B73B918F2330B00BB5F8E /* Supporting Files */ = { isa = PBXGroup; children = ( - DA5B73BA18F2330B00BB5F8E /* MDCSwipeToChoose-Prefix.pch */, + A59B81FD1B2E8ED00074A4F3 /* MDCSwipeToChoose-prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; diff --git a/MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch b/MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch index a98b8e8..8d05ea2 100644 --- a/MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch +++ b/MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch @@ -29,5 +29,5 @@ // #ifdef __OBJC__ - #import +#import #endif diff --git a/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m b/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m index 99cc0ba..d38dbd5 100644 --- a/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m +++ b/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m @@ -35,7 +35,7 @@ - (instancetype)init { if (self) { _swipeCancelledAnimationDuration = 0.2; _swipeCancelledAnimationOptions = UIViewAnimationOptionCurveEaseOut; - _swipeAnimationDuration = 0.1; + _swipeAnimationDuration = 1.0f; _swipeAnimationOptions = UIViewAnimationOptionCurveEaseIn; _rotationFactor = 3.f; diff --git a/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.h b/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.h index b312df5..914d2c2 100644 --- a/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.h +++ b/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.h @@ -37,52 +37,76 @@ @property (nonatomic, weak) id delegate; /*! - * The text displayed in the `likedView`. A default value is provided in the + * The text displayed in the `yesView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, copy) NSString *likedText; +@property (nonatomic, copy) NSString *yesText; /*! - * The color of the text and border of the `likedView`. A default value is provided in the + * The color of the text and border of the `yesView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, strong) UIColor *likedColor; +@property (nonatomic, strong) UIColor *yesColor; /*! - * The image used to displayed in the `likeView`. If this is present, it will take - * precedence over the likeText + * The image used to displayed in the `yesView`. If this is present, it will take + * precedence over the yesText */ -@property (nonatomic, strong) UIImage *likedImage; +@property (nonatomic, strong) UIImage *yesImage; /*! - * The rotation angle of the `likedView`. A default value is provided in the + * The rotation angle of the `yesView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, assign) CGFloat likedRotationAngle; +@property (nonatomic, assign) CGFloat yesRotationAngle; /*! - * The text displayed in the `nopeView`. A default value is provided in the + * The text displayed in the `noView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, copy) NSString *nopeText; +@property (nonatomic, copy) NSString *noText; /*! - * The color of the text and border of the `nopeView`. A default value is provided in the + * The color of the text and border of the `noView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, strong) UIColor *nopeColor; +@property (nonatomic, strong) UIColor *noColor; /*! - * The image used to displayed in the `nopeView`. If this is present, it will take - * precedence over the nopeText + * The image used to displayed in the `noView`. If this is present, it will take + * precedence over the noText */ -@property (nonatomic, strong) UIImage *nopeImage; +@property (nonatomic, strong) UIImage *noImage; /*! - * The rotation angle of the `nopeView`. A default value is provided in the + * The rotation angle of the `noView`. A default value is provided in the * `-init` method. */ -@property (nonatomic, assign) CGFloat nopeRotationAngle; +@property (nonatomic, assign) CGFloat noRotationAngle; + +/*! + * The text displayed in the `noView`. A default value is provided in the + * `-init` method. + */ +@property (nonatomic, copy) NSString *maybeText; + +/*! + * The color of the text and border of the `maybeView`. A default value is provided in the + * `-init` method. + */ +@property (nonatomic, strong) UIColor *maybeColor; + +/*! + * The image used to displayed in the `maybeView`. If this is present, it will take + * precedence over the noText + */ +@property (nonatomic, strong) UIImage *maybeImage; + +/*! + * The rotation angle of the `maybeView`. A default value is provided in the + * `-init` method. + */ +@property (nonatomic, assign) CGFloat maybeRotationAngle; /*! * The distance, in pixels, that a view must be panned in order to constitue a selection. diff --git a/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.m b/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.m index fb79dc5..3b4c0bf 100644 --- a/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.m +++ b/MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.m @@ -30,14 +30,18 @@ @implementation MDCSwipeToChooseViewOptions - (instancetype)init { self = [super init]; if (self) { - _likedText = [NSLocalizedString(@"liked", nil) uppercaseString]; - _likedColor = [UIColor colorWith8BitRed:29.f green:245.f blue:106.f alpha:1.f]; - _likedRotationAngle = -15.f; - - _nopeText = [NSLocalizedString(@"nope", nil) uppercaseString]; - _nopeColor = [UIColor colorWith8BitRed:247.f green:91.f blue:37.f alpha:1.f]; - _nopeRotationAngle = 15.f; + _yesText = [NSLocalizedString(@"Yes", nil) uppercaseString]; + _yesColor = [UIColor colorWith8BitRed:29.f green:245.f blue:106.f alpha:1.f]; + _yesRotationAngle = -15.f; + _noText = [NSLocalizedString(@"No", nil) uppercaseString]; + _noColor = [UIColor colorWith8BitRed:247.f green:91.f blue:37.f alpha:1.f]; + _noRotationAngle = 15.f; + + _maybeText = [NSLocalizedString(@"Maybe", nil) uppercaseString]; + _maybeColor = [UIColor colorWith8BitRed:227.f green:214.f blue:0.f alpha:1.f]; + _maybeRotationAngle = 0.f; + _threshold = 100.f; } return self; diff --git a/MDCSwipeToChoose/Public/State/MDCSwipeDirection.h b/MDCSwipeToChoose/Public/State/MDCSwipeDirection.h index 558fa0b..e657f7e 100644 --- a/MDCSwipeToChoose/Public/State/MDCSwipeDirection.h +++ b/MDCSwipeToChoose/Public/State/MDCSwipeDirection.h @@ -32,5 +32,6 @@ typedef NS_ENUM(NSInteger, MDCSwipeDirection) { MDCSwipeDirectionNone = 0, MDCSwipeDirectionLeft, - MDCSwipeDirectionRight + MDCSwipeDirectionRight, + MDCSwipeDirectionVertical }; diff --git a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.h b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.h index 34a598a..ba49692 100644 --- a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.h +++ b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.h @@ -28,24 +28,29 @@ /*! * A `UIView` subclass that acts nearly identically to the swipe-to-choose - * views in Tinder.app. Swipe right to "like", left to "dislike". + * views in Tinder.app. Swipe right to "yes", left to "no", or up/down to "maybe". */ @interface MDCSwipeToChooseView : UIView /*! - * The main image to be displayed and then "liked" or "disliked". + * The main image to be displayed and then "yes'd" or "no'd". */ @property (nonatomic, strong) UIImageView *imageView; /*! - * The "liked" view, which fades in as the `MDCSwipeToChooseView` is panned to the right. + * The "yes" view, which fades in as the `MDCSwipeToChooseView` is panned to the right. */ -@property (nonatomic, strong) UIView *likedView; +@property (nonatomic, strong) UIView *yesView; /*! - * The "nope" view, which fades in as the `MDCSwipeToChooseView` is panned to the left. + * The "no" view, which fades in as the `MDCSwipeToChooseView` is panned to the left. */ -@property (nonatomic, strong) UIView *nopeView; +@property (nonatomic, strong) UIView *noView; + +/*! + * The "maybeView" view, which fades in as the `MDCSwipeToChooseView` is panned to the up/down. + */ +@property (nonatomic, strong) UIView *maybeView; /*! * The designated initializer takes a `frame` and a set of options to customize diff --git a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m index cbd9955..5da048e 100644 --- a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m +++ b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m @@ -48,8 +48,9 @@ - (instancetype)initWithFrame:(CGRect)frame options:(MDCSwipeToChooseViewOptions _options = options ? options : [MDCSwipeToChooseViewOptions new]; [self setupView]; [self constructImageView]; - [self constructLikedView]; - [self constructNopeView]; + [self constructYesView]; + [self constructNoView]; + [self constructMaybeView]; [self setupSwipeToChoose]; } return self; @@ -74,47 +75,69 @@ - (void)constructImageView { [self addSubview:_imageView]; } -- (void)constructLikedView { - CGFloat yOrigin = (self.options.likedImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); +- (void)constructYesView { + CGFloat yOrigin = (self.options.yesImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); CGRect frame = CGRectMake(MDCSwipeToChooseViewHorizontalPadding, yOrigin, CGRectGetMidX(self.imageView.bounds), MDCSwipeToChooseViewLabelWidth); - if (self.options.likedImage) { - self.likedView = [[UIImageView alloc] initWithImage:self.options.likedImage]; - self.likedView.frame = frame; - self.likedView.contentMode = UIViewContentModeScaleAspectFit; + if (self.options.yesImage) { + self.yesView = [[UIImageView alloc] initWithImage:self.options.yesImage]; + self.yesView.frame = frame; + self.yesView.contentMode = UIViewContentModeScaleAspectFit; } else { - self.likedView = [[UIView alloc] initWithFrame:frame]; - [self.likedView constructBorderedLabelWithText:self.options.likedText - color:self.options.likedColor - angle:self.options.likedRotationAngle]; + self.yesView = [[UIView alloc] initWithFrame:frame]; + [self.yesView constructBorderedLabelWithText:self.options.yesText + color:self.options.yesColor + angle:self.options.yesRotationAngle]; } - self.likedView.alpha = 0.f; - [self.imageView addSubview:self.likedView]; + self.yesView.alpha = 0.f; + [self.imageView addSubview:self.yesView]; } -- (void)constructNopeView { +- (void)constructNoView { CGFloat width = CGRectGetMidX(self.imageView.bounds); CGFloat xOrigin = CGRectGetMaxX(self.imageView.bounds) - width - MDCSwipeToChooseViewHorizontalPadding; - CGFloat yOrigin = (self.options.nopeImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); + CGFloat yOrigin = (self.options.noImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); CGRect frame = CGRectMake(xOrigin, yOrigin, width, MDCSwipeToChooseViewLabelWidth); - if (self.options.nopeImage) { - self.nopeView = [[UIImageView alloc] initWithImage:self.options.nopeImage]; - self.nopeView.frame = frame; - self.nopeView.contentMode = UIViewContentModeScaleAspectFit; + if (self.options.noImage) { + self.noView = [[UIImageView alloc] initWithImage:self.options.noImage]; + self.noView.frame = frame; + self.noView.contentMode = UIViewContentModeScaleAspectFit; } else { - self.nopeView = [[UIView alloc] initWithFrame:frame]; - [self.nopeView constructBorderedLabelWithText:self.options.nopeText - color:self.options.nopeColor - angle:self.options.nopeRotationAngle]; + self.noView = [[UIView alloc] initWithFrame:frame]; + [self.noView constructBorderedLabelWithText:self.options.noText + color:self.options.noColor + angle:self.options.noRotationAngle]; } - self.nopeView.alpha = 0.f; - [self.imageView addSubview:self.nopeView]; + self.noView.alpha = 0.f; + [self.imageView addSubview:self.noView]; +} + +- (void)constructMaybeView { + CGFloat width = CGRectGetMidX(self.imageView.bounds); + CGFloat xOrigin = CGRectGetMaxX(self.imageView.bounds) - width - MDCSwipeToChooseViewHorizontalPadding; + CGFloat yOrigin = (self.options.maybeImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); + CGRect frame = CGRectMake(xOrigin, + yOrigin, + width, + MDCSwipeToChooseViewLabelWidth); + if (self.options.maybeImage) { + self.maybeView = [[UIImageView alloc] initWithImage:self.options.maybeImage]; + self.maybeView.frame = frame; + self.maybeView.contentMode = UIViewContentModeScaleAspectFit; + } else { + self.maybeView = [[UIView alloc] initWithFrame:frame]; + [self.maybeView constructBorderedLabelWithText:self.options.maybeText + color:self.options.maybeColor + angle:self.options.maybeRotationAngle]; + } + self.maybeView.alpha = 0.f; + [self.imageView addSubview:self.maybeView]; } - (void)setupSwipeToChoose { @@ -122,19 +145,29 @@ - (void)setupSwipeToChoose { options.delegate = self.options.delegate; options.threshold = self.options.threshold; - __block UIView *likedImageView = self.likedView; - __block UIView *nopeImageView = self.nopeView; + __block UIView *yesImageView = self.yesView; + __block UIView *noImageView = self.noView; + __block UIView *maybeImageView = self.maybeView; + __weak MDCSwipeToChooseView *weakself = self; options.onPan = ^(MDCPanState *state) { if (state.direction == MDCSwipeDirectionNone) { - likedImageView.alpha = 0.f; - nopeImageView.alpha = 0.f; + yesImageView.alpha = 0.f; + noImageView.alpha = 0.f; + maybeImageView.alpha = 0.f; } else if (state.direction == MDCSwipeDirectionLeft) { - likedImageView.alpha = 0.f; - nopeImageView.alpha = state.thresholdRatio; + yesImageView.alpha = 0.f; + noImageView.alpha = state.thresholdRatio; + maybeImageView.alpha = 0.f; } else if (state.direction == MDCSwipeDirectionRight) { - likedImageView.alpha = state.thresholdRatio; - nopeImageView.alpha = 0.f; + yesImageView.alpha = state.thresholdRatio; + noImageView.alpha = 0.f; + maybeImageView.alpha = 0.f; + } + else if (state.direction == MDCSwipeDirectionVertical) { + yesImageView.alpha = 0.f; + noImageView.alpha = 0.f; + maybeImageView.alpha = state.thresholdRatio; } if (weakself.options.onPan) { diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index 574ef86..738c657 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -174,13 +174,19 @@ - (void)mdc_exitSuperviewFromTranslation:(CGPoint)translation { - (void)mdc_executeOnPanBlockForTranslation:(CGPoint)translation { if (self.mdc_options.onPan) { - CGFloat thresholdRatio = MIN(1.f, fabs(translation.x)/self.mdc_options.threshold); + CGFloat thresholdRatio; MDCSwipeDirection direction = MDCSwipeDirectionNone; - if (translation.x > 0.f) { - direction = MDCSwipeDirectionRight; - } else if (translation.x < 0.f) { - direction = MDCSwipeDirectionLeft; + if (ABS(translation.y) > ABS(translation.x)) { + direction = MDCSwipeDirectionVertical; + thresholdRatio = MIN(1.f, fabs(translation.y)/self.mdc_options.threshold); + } else { + thresholdRatio = MIN(1.f, fabs(translation.x)/self.mdc_options.threshold); + if (translation.x > 0.f) { + direction = MDCSwipeDirectionRight; + } else if (translation.x < 0.f) { + direction = MDCSwipeDirectionLeft; + } } MDCPanState *state = [MDCPanState new]; @@ -252,8 +258,7 @@ - (void)mdc_onSwipeToChoosePanGestureRecognizer:(UIPanGestureRecognizer *)panGes // the updates via the pan block. CGPoint translation = [panGestureRecognizer translationInView:view]; view.center = MDCCGPointAdd(self.mdc_viewState.originalCenter, translation); - [self mdc_rotateForTranslation:translation - rotationDirection:self.mdc_viewState.rotationDirection]; + [self mdc_rotateForTranslation:translation rotationDirection:self.mdc_viewState.rotationDirection]; [self mdc_executeOnPanBlockForTranslation:translation]; } } From 51aa7a5db3156f8d3e5e2be477ef1ca52cdd2696 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 01:10:11 -0400 Subject: [PATCH 3/8] Add vertical swipe to switch when checking for exit swipe --- MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m | 2 +- MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m | 6 +++--- MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m b/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m index d38dbd5..74ccc72 100644 --- a/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m +++ b/MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m @@ -35,7 +35,7 @@ - (instancetype)init { if (self) { _swipeCancelledAnimationDuration = 0.2; _swipeCancelledAnimationOptions = UIViewAnimationOptionCurveEaseOut; - _swipeAnimationDuration = 1.0f; + _swipeAnimationDuration = 0.3f; _swipeAnimationOptions = UIViewAnimationOptionCurveEaseIn; _rotationFactor = 3.f; diff --git a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m index 5da048e..837413c 100644 --- a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m +++ b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m @@ -165,9 +165,9 @@ - (void)setupSwipeToChoose { maybeImageView.alpha = 0.f; } else if (state.direction == MDCSwipeDirectionVertical) { - yesImageView.alpha = 0.f; - noImageView.alpha = 0.f; - maybeImageView.alpha = state.thresholdRatio; + yesImageView.alpha = 0.f; + noImageView.alpha = 0.f; + maybeImageView.alpha = state.thresholdRatio; } if (weakself.options.onPan) { diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index 738c657..b50c46f 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -118,9 +118,9 @@ - (void)mdc_finalizePosition { MDCSwipeDirection direction = [self mdc_directionOfExceededThreshold]; switch (direction) { case MDCSwipeDirectionRight: + case MDCSwipeDirectionVertical: case MDCSwipeDirectionLeft: { - CGPoint translation = MDCCGPointSubtract(self.center, - self.mdc_viewState.originalCenter); + CGPoint translation = MDCCGPointSubtract(self.center, self.mdc_viewState.originalCenter); [self mdc_exitSuperviewFromTranslation:translation]; break; } From c2c1173f0ab72f8ca682d6ab3baa5651c50d3846 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 01:13:21 -0400 Subject: [PATCH 4/8] Add vertical swipe to directionofexceededthreshold method --- MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index b50c46f..cbda49d 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -229,6 +229,8 @@ - (MDCSwipeDirection)mdc_directionOfExceededThreshold { return MDCSwipeDirectionRight; } else if (self.center.x < self.mdc_viewState.originalCenter.x - self.mdc_options.threshold) { return MDCSwipeDirectionLeft; + } else if (self.center.y < self.mdc_viewState.originalCenter.y - self.mdc_options.threshold) { + return MDCSwipeDirectionVertical; } else { return MDCSwipeDirectionNone; } From 09f71b366b09f0eafd651835cbc2c18f7d65a4d0 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 01:16:01 -0400 Subject: [PATCH 5/8] Detect both up and down swipes as a 'maybe' --- MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index cbda49d..746364f 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -229,7 +229,7 @@ - (MDCSwipeDirection)mdc_directionOfExceededThreshold { return MDCSwipeDirectionRight; } else if (self.center.x < self.mdc_viewState.originalCenter.x - self.mdc_options.threshold) { return MDCSwipeDirectionLeft; - } else if (self.center.y < self.mdc_viewState.originalCenter.y - self.mdc_options.threshold) { + } else if (ABS(self.center.y - self.mdc_viewState.originalCenter.y) > self.mdc_options.threshold) { return MDCSwipeDirectionVertical; } else { return MDCSwipeDirectionNone; From eaaef529681b84efbb09cc4fb197991fd6196392 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 01:45:43 -0400 Subject: [PATCH 6/8] Redesign labels and center them on the card + remove rotation of card (not needed with vertical swiping --- .../Internal/Views/UIView+MDCBorderedLabel.m | 1 + .../Public/Views/MDCSwipeToChooseView.m | 47 +++++++------------ .../Public/Views/UIView+MDCSwipeToChoose.m | 8 ---- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/MDCSwipeToChoose/Internal/Views/UIView+MDCBorderedLabel.m b/MDCSwipeToChoose/Internal/Views/UIView+MDCBorderedLabel.m index 9367fcc..30ca56b 100644 --- a/MDCSwipeToChoose/Internal/Views/UIView+MDCBorderedLabel.m +++ b/MDCSwipeToChoose/Internal/Views/UIView+MDCBorderedLabel.m @@ -34,6 +34,7 @@ - (void)constructBorderedLabelWithText:(NSString *)text self.layer.borderColor = color.CGColor; self.layer.borderWidth = 5.f; self.layer.cornerRadius = 10.f; + self.layer.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7f].CGColor; UILabel *label = [[UILabel alloc] initWithFrame:self.bounds]; label.text = [text uppercaseString]; diff --git a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m index 837413c..9859bd7 100644 --- a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m +++ b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m @@ -76,12 +76,9 @@ - (void)constructImageView { } - (void)constructYesView { - CGFloat yOrigin = (self.options.yesImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); - - CGRect frame = CGRectMake(MDCSwipeToChooseViewHorizontalPadding, - yOrigin, - CGRectGetMidX(self.imageView.bounds), - MDCSwipeToChooseViewLabelWidth); + CGFloat width = self.imageView.frame.size.width - 2*MDCSwipeToChooseViewHorizontalPadding; + CGFloat height = self.imageView.frame.size.height/4; + CGRect frame = CGRectMake(MDCSwipeToChooseViewHorizontalPadding, self.imageView.frame.size.height/2 - height/2, width, height); if (self.options.yesImage) { self.yesView = [[UIImageView alloc] initWithImage:self.options.yesImage]; self.yesView.frame = frame; @@ -97,13 +94,9 @@ - (void)constructYesView { } - (void)constructNoView { - CGFloat width = CGRectGetMidX(self.imageView.bounds); - CGFloat xOrigin = CGRectGetMaxX(self.imageView.bounds) - width - MDCSwipeToChooseViewHorizontalPadding; - CGFloat yOrigin = (self.options.noImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); - CGRect frame = CGRectMake(xOrigin, - yOrigin, - width, - MDCSwipeToChooseViewLabelWidth); + CGFloat width = self.imageView.frame.size.width - 2*MDCSwipeToChooseViewHorizontalPadding; + CGFloat height = self.imageView.frame.size.height/4; + CGRect frame = CGRectMake(MDCSwipeToChooseViewHorizontalPadding, self.imageView.frame.size.height/2 - height/2, width, height); if (self.options.noImage) { self.noView = [[UIImageView alloc] initWithImage:self.options.noImage]; self.noView.frame = frame; @@ -119,22 +112,18 @@ - (void)constructNoView { } - (void)constructMaybeView { - CGFloat width = CGRectGetMidX(self.imageView.bounds); - CGFloat xOrigin = CGRectGetMaxX(self.imageView.bounds) - width - MDCSwipeToChooseViewHorizontalPadding; - CGFloat yOrigin = (self.options.maybeImage ? MDCSwipeToChooseViewImageTopPadding : MDCSwipeToChooseViewTopPadding); - CGRect frame = CGRectMake(xOrigin, - yOrigin, - width, - MDCSwipeToChooseViewLabelWidth); - if (self.options.maybeImage) { - self.maybeView = [[UIImageView alloc] initWithImage:self.options.maybeImage]; - self.maybeView.frame = frame; - self.maybeView.contentMode = UIViewContentModeScaleAspectFit; - } else { - self.maybeView = [[UIView alloc] initWithFrame:frame]; - [self.maybeView constructBorderedLabelWithText:self.options.maybeText - color:self.options.maybeColor - angle:self.options.maybeRotationAngle]; + CGFloat width = self.imageView.frame.size.width - 2*MDCSwipeToChooseViewHorizontalPadding; + CGFloat height = self.imageView.frame.size.height/4; + CGRect frame = CGRectMake(MDCSwipeToChooseViewHorizontalPadding, self.imageView.frame.size.height/2 - height/2, width, height); + if (self.options.maybeImage) { + self.maybeView = [[UIImageView alloc] initWithImage:self.options.maybeImage]; + self.maybeView.frame = frame; + self.maybeView.contentMode = UIViewContentModeScaleAspectFit; + } else { + self.maybeView = [[UIView alloc] initWithFrame:frame]; + [self.maybeView constructBorderedLabelWithText:self.options.maybeText + color:self.options.maybeColor + angle:self.options.maybeRotationAngle]; } self.maybeView.alpha = 0.f; [self.imageView addSubview:self.maybeView]; diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index 746364f..63a562f 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -244,14 +244,6 @@ - (void)mdc_onSwipeToChoosePanGestureRecognizer:(UIPanGestureRecognizer *)panGes if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) { self.mdc_viewState.originalCenter = view.center; self.mdc_viewState.originalTransform = view.layer.transform; - - // If the pan gesture originated at the top half of the view, rotate the view - // away from the center. Otherwise, rotate towards the center. - if ([panGestureRecognizer locationInView:view].y < view.center.y) { - self.mdc_viewState.rotationDirection = MDCRotationAwayFromCenter; - } else { - self.mdc_viewState.rotationDirection = MDCRotationTowardsCenter; - } } else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { // Either move the view back to its original position or move it off screen. [self mdc_finalizePosition]; From 36c9b3a02774ac911620be83b5735d3edcc6ed1d Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 02:07:23 -0400 Subject: [PATCH 7/8] Remove unused constants --- MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m index 9859bd7..c2edb64 100644 --- a/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m +++ b/MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m @@ -30,9 +30,6 @@ #import static CGFloat const MDCSwipeToChooseViewHorizontalPadding = 10.f; -static CGFloat const MDCSwipeToChooseViewTopPadding = 20.f; -static CGFloat const MDCSwipeToChooseViewImageTopPadding = 100.f; -static CGFloat const MDCSwipeToChooseViewLabelWidth = 65.f; @interface MDCSwipeToChooseView () @property (nonatomic, strong) MDCSwipeToChooseViewOptions *options; From 3a32cfde211d8c531a209a829dfcf2fdd9952623 Mon Sep 17 00:00:00 2001 From: Bryan Crampton Date: Mon, 15 Jun 2015 14:19:19 -0400 Subject: [PATCH 8/8] Allow progamatic vertical swiping --- MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m index 63a562f..2534c2f 100644 --- a/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m +++ b/MDCSwipeToChoose/Public/Views/UIView+MDCSwipeToChoose.m @@ -217,6 +217,9 @@ - (CGPoint)mdc_translationExceedingThreshold:(CGFloat)threshold return CGPointMake(-offset, 0); case MDCSwipeDirectionRight: return CGPointMake(offset, 0); + case MDCSwipeDirectionVertical: + return CGPointMake(0, -offset); + default: [NSException raise:NSInternalInconsistencyException format:@"Invallid direction argument."];