mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
124 lines
4.4 KiB
Objective-C
Executable file
124 lines
4.4 KiB
Objective-C
Executable file
//
|
|
// SloppySwiper.m
|
|
//
|
|
// Created by Arkadiusz Holko http://holko.pl on 29-05-14.
|
|
//
|
|
|
|
#import "SloppySwiper.h"
|
|
#import "SSWAnimator.h"
|
|
#import "SSWDirectionalPanGestureRecognizer.h"
|
|
|
|
@interface SloppySwiper()
|
|
@property (weak, readwrite, nonatomic) UIPanGestureRecognizer *panRecognizer;
|
|
@property (weak, nonatomic) IBOutlet UINavigationController *navigationController;
|
|
@property (strong, nonatomic) SSWAnimator *animator;
|
|
@property (strong, nonatomic) UIPercentDrivenInteractiveTransition *interactionController;
|
|
/// A Boolean value that indicates whether the navigation controller is currently animating a push/pop operation.
|
|
@property (nonatomic) BOOL duringAnimation;
|
|
@end
|
|
|
|
@implementation SloppySwiper
|
|
|
|
#pragma mark - Lifecycle
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_panRecognizer removeTarget:self action:@selector(pan:)];
|
|
[_navigationController.view removeGestureRecognizer:_panRecognizer];
|
|
}
|
|
|
|
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
|
|
{
|
|
NSCParameterAssert(!!navigationController);
|
|
|
|
self = [super init];
|
|
if (self) {
|
|
_navigationController = navigationController;
|
|
[self commonInit];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)awakeFromNib
|
|
{
|
|
[super awakeFromNib];
|
|
|
|
[self commonInit];
|
|
}
|
|
|
|
- (void)commonInit
|
|
{
|
|
SSWDirectionalPanGestureRecognizer *panRecognizer = [[SSWDirectionalPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
|
|
panRecognizer.direction = SSWPanDirectionRight;
|
|
panRecognizer.maximumNumberOfTouches = 1;
|
|
[_navigationController.view addGestureRecognizer:panRecognizer];
|
|
_panRecognizer = panRecognizer;
|
|
|
|
_animator = [[SSWAnimator alloc] init];
|
|
}
|
|
|
|
#pragma mark - UIPanGestureRecognizer
|
|
|
|
- (void)pan:(UIPanGestureRecognizer*)recognizer
|
|
{
|
|
UIView *view = self.navigationController.view;
|
|
if (recognizer.state == UIGestureRecognizerStateBegan) {
|
|
if (self.navigationController.viewControllers.count > 1 && !self.duringAnimation) {
|
|
self.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];
|
|
self.interactionController.completionCurve = UIViewAnimationCurveEaseOut;
|
|
|
|
[self.navigationController popViewControllerAnimated:YES];
|
|
}
|
|
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
|
|
CGPoint translation = [recognizer translationInView:view];
|
|
// Cumulative translation.x can be less than zero because user can pan slightly to the right and then back to the left.
|
|
CGFloat d = translation.x > 0 ? translation.x / CGRectGetWidth(view.bounds) : 0;
|
|
[self.interactionController updateInteractiveTransition:d];
|
|
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
|
|
if ([recognizer velocityInView:view].x > 0) {
|
|
[self.interactionController finishInteractiveTransition];
|
|
} else {
|
|
[self.interactionController cancelInteractiveTransition];
|
|
// When the transition is cancelled, `navigationController:didShowViewController:animated:` isn't called, so we have to maintain `duringAnimation`'s state here too.
|
|
self.duringAnimation = NO;
|
|
}
|
|
self.interactionController = nil;
|
|
}
|
|
}
|
|
|
|
#pragma mark - UINavigationControllerDelegate
|
|
|
|
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
|
|
{
|
|
if (operation == UINavigationControllerOperationPop) {
|
|
return self.animator;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
|
|
{
|
|
return self.interactionController;
|
|
}
|
|
|
|
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
|
{
|
|
if (animated) {
|
|
self.duringAnimation = YES;
|
|
}
|
|
}
|
|
|
|
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
|
{
|
|
self.duringAnimation = NO;
|
|
|
|
if (navigationController.viewControllers.count <= 1) {
|
|
self.panRecognizer.enabled = NO;
|
|
}
|
|
else {
|
|
self.panRecognizer.enabled = YES;
|
|
}
|
|
}
|
|
|
|
@end
|