Skip to content
This repository was archived by the owner on Aug 30, 2023. It is now read-only.

Add support for interactive transitioning #27

Open
wants to merge 1 commit into
base: develop
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
7 changes: 7 additions & 0 deletions src/MDMTransition.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import <UIKit/UIKit.h>

@protocol MDMTransitionContext;
@protocol MDMInteractiveTransitionContext;

/**
A transition coordinates the animated presentation or dismissal of a view controller.
Expand Down Expand Up @@ -111,3 +112,9 @@ NS_SWIFT_NAME(presentationController(forPresented:presenting:source:));
// clang-format on

@end

NS_SWIFT_NAME(InteractiveTransition)
@protocol MDMInteractiveTransition <NSObject>
- (Boolean)isInteractive:(nonnull id<MDMTransitionContext>)context;
- (void)startWithInteractiveContext:(nonnull id<MDMInteractiveTransitionContext>)context;
@end
10 changes: 10 additions & 0 deletions src/MDMTransitionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ NS_SWIFT_NAME(TransitionContext)
*/
- (void)transitionDidEnd;

@property(nonatomic, readonly) BOOL wasCancelled;

/**
The direction this transition is moving in.
*/
Expand Down Expand Up @@ -84,3 +86,11 @@ NS_SWIFT_NAME(TransitionContext)
*/
@property(nonatomic, strong, readonly, nullable) UIPresentationController *presentationController;
@end

NS_SWIFT_NAME(InteractiveTransitionContext)
@protocol MDMInteractiveTransitionContext <MDMTransitionContext>
- (UIPercentDrivenInteractiveTransition *_Nonnull)getPercentIT;
- (void)updatePercent:(CGFloat)percent;
- (void)finishInteractiveTransition;
- (void)cancelInteractiveTransition;
@end
2 changes: 1 addition & 1 deletion src/MDMTransitionController.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import <Foundation/Foundation.h>

@protocol MDMTransition;
@protocol MDMInteractiveTransition;

/**
A transition controller is a bridge between UIKit's view controller transitioning APIs and
Expand Down Expand Up @@ -44,5 +45,4 @@ NS_SWIFT_NAME(TransitionController)
This may be non-nil while a transition is active.
*/
@property(nonatomic, strong, nullable, readonly) id<MDMTransition> activeTransition;

@end
2 changes: 2 additions & 0 deletions src/UIViewController+TransitionController.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import <UIKit/UIKit.h>

@protocol MDMTransitionController;
@protocol MDMInteractiveTransitionContext;

@interface UIViewController (MDMTransitionController)

Expand All @@ -32,4 +33,5 @@
@property(nonatomic, strong, readonly, nonnull) id<MDMTransitionController> mdm_transitionController
NS_SWIFT_NAME(transitionController);

@property(nonatomic, strong, nullable) id<MDMInteractiveTransitionContext> interactiveTransitionContext;
@end
10 changes: 10 additions & 0 deletions src/UIViewController+TransitionController.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ @implementation UIViewController (MDMTransitionController)

#pragma mark - Public

- (id<MDMInteractiveTransition>)interactiveTransitionContext {
//const void *key = [self mdm_transitionControllerKey];
return objc_getAssociatedObject(self, "interactions");
}

- (void)setInteractiveTransitionContext:(id<MDMInteractiveTransition>)interactiveTransition {
//const void *key = [self mdm_transitionControllerKey];
objc_setAssociatedObject(self, "interactions", interactiveTransition, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id<MDMTransitionController>)mdm_transitionController {
const void *key = [self mdm_transitionControllerKey];

Expand Down
40 changes: 40 additions & 0 deletions src/private/MDMPresentationTransitionController.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ - (void)setTransition:(id<MDMTransition>)transition {
return _context;
}

- (nullable id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)animator {
return [self prepareForInteractiveTransition];
}

- (nullable id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator {
return [self prepareForInteractiveTransition];
}

// Presentation

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented
Expand Down Expand Up @@ -129,4 +137,36 @@ - (void)prepareForTransitionWithSourceViewController:(nullable UIViewController
}
}

- (nullable id<UIViewControllerInteractiveTransitioning>)prepareForInteractiveTransition {
Boolean isInteractive = false;

Boolean isInteractiveResponds = false;
Boolean startWithInteractiveResponds = false;

if ([_transition respondsToSelector:@selector(isInteractive:)]) {
isInteractiveResponds = true;
} else {
return nil;
}

if ([_transition respondsToSelector:@selector(startWithInteractiveContext:)]) {
startWithInteractiveResponds = true;
} else {
return nil;
}

if (isInteractiveResponds && startWithInteractiveResponds) {
id<MDMInteractiveTransition> interactiveTransition = (id<MDMInteractiveTransition>)_transition;
isInteractive = [interactiveTransition isInteractive:_context];
if (isInteractive) {
[interactiveTransition startWithInteractiveContext:_context];
}
}

UIPercentDrivenInteractiveTransition *pdi = [_context getPercentIT];
// Setting the completion speed to a value close to 1.0 prevents
// the bar from sometimes jumping.
pdi.completionSpeed = 0.933;
return isInteractive == false ? nil : pdi;
}
@end
2 changes: 1 addition & 1 deletion src/private/MDMViewControllerTransitionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@protocol MDMTransition;
@protocol MDMViewControllerTransitionContextDelegate;

@interface MDMViewControllerTransitionContext : NSObject <MDMTransitionContext, UIViewControllerAnimatedTransitioning>
@interface MDMViewControllerTransitionContext : NSObject <MDMTransitionContext, MDMInteractiveTransitionContext, UIViewControllerAnimatedTransitioning>

- (nonnull instancetype)initWithTransition:(nonnull id<MDMTransition>)transition
direction:(MDMTransitionDirection)direction
Expand Down
29 changes: 27 additions & 2 deletions src/private/MDMViewControllerTransitionContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@

@implementation MDMViewControllerTransitionContext {
id<UIViewControllerContextTransitioning> _transitionContext;
UIPercentDrivenInteractiveTransition *_percent;
}

@synthesize direction = _direction;
@synthesize sourceViewController = _sourceViewController;
@synthesize backViewController = _backViewController;
@synthesize foreViewController = _foreViewController;
@synthesize presentationController = _presentationController;

@synthesize wasCancelled = _wasCancelled;
- (nonnull instancetype)initWithTransition:(nonnull id<MDMTransition>)transition
direction:(MDMTransitionDirection)direction
sourceViewController:(nullable UIViewController *)sourceViewController
Expand All @@ -44,6 +45,7 @@ - (nonnull instancetype)initWithTransition:(nonnull id<MDMTransition>)transition
_presentationController = presentationController;

_transition = [self fallbackForTransition:_transition];
_percent = [[UIPercentDrivenInteractiveTransition alloc] init];
}
if (!_transition) {
return nil;
Expand Down Expand Up @@ -82,7 +84,14 @@ - (UIView *)containerView {
}

- (void)transitionDidEnd {
[_transitionContext completeTransition:true];
BOOL wasCanceled = [_transitionContext transitionWasCancelled];
if (wasCanceled) {
_wasCancelled = false;
[_transitionContext completeTransition:false];
} else {
_wasCancelled = true;
[_transitionContext completeTransition:true];
}

_transition = nil;

Expand Down Expand Up @@ -173,4 +182,20 @@ - (void)anticipateOnlyExplicitAnimations {
return transition;
}

- (UIPercentDrivenInteractiveTransition *_Nonnull)getPercentIT {
return _percent;
}

- (void)updatePercent:(CGFloat)percent {
[_percent updateInteractiveTransition:percent];
}

- (void)finishInteractiveTransition {
[_percent finishInteractiveTransition];
}

- (void)cancelInteractiveTransition {
[_percent cancelInteractiveTransition];
}

@end