Skip to content
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

Allow vertical swiping for a "maybe" #92

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions MDCSwipeToChoose-prefix.pch
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif

#import "Pods-environment.h"
4 changes: 2 additions & 2 deletions MDCSwipeToChoose.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "<group>"; };
DA06338118F23C2B009EBE62 /* MDCGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCGeometry.h; sourceTree = "<group>"; };
DA06338218F23C2B009EBE62 /* MDCGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDCGeometry.m; sourceTree = "<group>"; };
DA0633B118F23EAD009EBE62 /* MDCSwipeToChoose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCSwipeToChoose.h; sourceTree = "<group>"; };
Expand All @@ -69,7 +70,6 @@
DA0633D018F2F9E2009EBE62 /* MDCSwipeToChooseDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCSwipeToChooseDelegate.h; sourceTree = "<group>"; };
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 = "<group>"; };
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; };
Expand Down Expand Up @@ -207,7 +207,7 @@
DA5B73B918F2330B00BB5F8E /* Supporting Files */ = {
isa = PBXGroup;
children = (
DA5B73BA18F2330B00BB5F8E /* MDCSwipeToChoose-Prefix.pch */,
A59B81FD1B2E8ED00074A4F3 /* MDCSwipeToChoose-prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
Expand Down
1 change: 1 addition & 0 deletions MDCSwipeToChoose/Internal/Views/UIView+MDCBorderedLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion MDCSwipeToChoose/MDCSwipeToChoose-Prefix.pch
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@
//

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h>
#endif
2 changes: 1 addition & 1 deletion MDCSwipeToChoose/Public/Options/MDCSwipeOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ - (instancetype)init {
if (self) {
_swipeCancelledAnimationDuration = 0.2;
_swipeCancelledAnimationOptions = UIViewAnimationOptionCurveEaseOut;
_swipeAnimationDuration = 0.1;
_swipeAnimationDuration = 0.3f;
_swipeAnimationOptions = UIViewAnimationOptionCurveEaseIn;
_rotationFactor = 3.f;

Expand Down
60 changes: 42 additions & 18 deletions MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,52 +37,76 @@
@property (nonatomic, weak) id<MDCSwipeToChooseDelegate> 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.
Expand Down
18 changes: 11 additions & 7 deletions MDCSwipeToChoose/Public/Options/MDCSwipeToChooseViewOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion MDCSwipeToChoose/Public/State/MDCSwipeDirection.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@
typedef NS_ENUM(NSInteger, MDCSwipeDirection) {
MDCSwipeDirectionNone = 0,
MDCSwipeDirectionLeft,
MDCSwipeDirectionRight
MDCSwipeDirectionRight,
MDCSwipeDirectionVertical
};
17 changes: 11 additions & 6 deletions MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
115 changes: 67 additions & 48 deletions MDCSwipeToChoose/Public/Views/MDCSwipeToChooseView.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
#import <QuartzCore/QuartzCore.h>

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;
Expand All @@ -48,8 +45,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;
Expand All @@ -74,67 +72,88 @@ - (void)constructImageView {
[self addSubview:_imageView];
}

- (void)constructLikedView {
CGFloat yOrigin = (self.options.likedImage ? 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;
- (void)constructYesView {
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;
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 {
CGFloat width = CGRectGetMidX(self.imageView.bounds);
CGFloat xOrigin = CGRectGetMaxX(self.imageView.bounds) - width - MDCSwipeToChooseViewHorizontalPadding;
CGFloat yOrigin = (self.options.nopeImage ? 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;
- (void)constructNoView {
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;
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 = 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];
}

- (void)setupSwipeToChoose {
MDCSwipeOptions *options = [MDCSwipeOptions new];
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) {
Expand Down
Loading