Skip to content

Commit 8cce24b

Browse files
Add support for interactive transitioning
material-motion#3
1 parent 10daa68 commit 8cce24b

8 files changed

+153
-4
lines changed

src/MDMTransition.h

+7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import <UIKit/UIKit.h>
1818

1919
@protocol MDMTransitionContext;
20+
@protocol MDMInteractiveTransitionContext;
2021

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

113114
@end
115+
116+
NS_SWIFT_NAME(InteractiveTransition)
117+
@protocol MDMInteractiveTransition <NSObject>
118+
- (Boolean)isInteractive:(nonnull id<MDMTransitionContext>)context;
119+
- (void)startWithInteractiveContext:(nonnull id<MDMInteractiveTransitionContext>)context;
120+
@end

src/MDMTransitionController.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import <Foundation/Foundation.h>
1818

1919
@protocol MDMTransition;
20+
@protocol MDMInteractiveTransition;
2021

2122
/**
2223
A transition controller is a bridge between UIKit's view controller transitioning APIs and
@@ -44,5 +45,5 @@ NS_SWIFT_NAME(TransitionController)
4445
This may be non-nil while a transition is active.
4546
*/
4647
@property(nonatomic, strong, nullable, readonly) id<MDMTransition> activeTransition;
47-
48+
@property(nonatomic, strong, nullable) id<MDMInteractiveTransition> interactiveTransition;
4849
@end

src/UIViewController+TransitionController.h

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import <Foundation/Foundation.h>
1818

1919
@protocol MDMTransitionController;
20+
@protocol MDMInteractiveTransitionContext;
2021

2122
@interface UIViewController (MDMTransitionController)
2223

@@ -31,4 +32,5 @@
3132
@property(nonatomic, strong, readonly, nonnull) id<MDMTransitionController> mdm_transitionController
3233
NS_SWIFT_NAME(transitionController);
3334

35+
@property(nonatomic, strong, nullable) id<MDMInteractiveTransitionContext> interactiveTransitionContext;
3436
@end

src/UIViewController+TransitionController.m

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ @implementation UIViewController (MDMTransitionController)
2424

2525
#pragma mark - Public
2626

27+
- (id<MDMInteractiveTransition>)interactiveTransitionContext {
28+
//const void *key = [self mdm_transitionControllerKey];
29+
return objc_getAssociatedObject(self, "interactions");
30+
}
31+
32+
- (void)setInteractiveTransitionContext:(id<MDMInteractiveTransition>) interactiveTransition {
33+
//const void *key = [self mdm_transitionControllerKey];
34+
objc_setAssociatedObject(self, "interactions", interactiveTransition, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
35+
}
36+
2737
- (id<MDMTransitionController>)mdm_transitionController {
2838
const void *key = [self mdm_transitionControllerKey];
2939

src/private/MDMPresentationTransitionController.m

+46
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#import "MDMPresentationTransitionController.h"
1818

1919
#import "MDMTransition.h"
20+
#import "MDMViewControllerInteractiveTransitionContext.h"
2021
#import "MDMViewControllerTransitionContext.h"
2122

2223
@interface MDMPresentationTransitionController () <UIViewControllerTransitioningDelegate, MDMViewControllerTransitionContextDelegate>
@@ -30,10 +31,12 @@ @implementation MDMPresentationTransitionController {
3031
UIPresentationController *_presentationController;
3132

3233
MDMViewControllerTransitionContext *_context;
34+
MDMViewControllerInteractiveTransitionContext *_interactiveContext;
3335
__weak UIViewController *_source;
3436
}
3537

3638
@synthesize transition = _transition;
39+
@synthesize interactiveTransition = _interactiveTransition;
3740

3841
- (nonnull instancetype)initWithViewController:(nonnull UIViewController *)viewController {
3942
self = [super init];
@@ -60,6 +63,10 @@ - (void)setTransition:(id<MDMTransition>)transition {
6063
return _context.transition;
6164
}
6265

66+
- (void)setInteractiveTransition:(id<MDMInteractiveTransition>)transition {
67+
_interactiveTransition = transition;
68+
}
69+
6370
#pragma mark - UIViewControllerTransitioningDelegate
6471

6572
// Animated transitions
@@ -84,6 +91,14 @@ - (void)setTransition:(id<MDMTransition>)transition {
8491
return _context;
8592
}
8693

94+
- (nullable id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)animator {
95+
return [self prepareForInteractiveTransition];
96+
}
97+
98+
- (nullable id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator {
99+
return [self prepareForInteractiveTransition];
100+
}
101+
87102
// Presentation
88103

89104
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented
@@ -129,4 +144,35 @@ - (void)prepareForTransitionWithSourceViewController:(nullable UIViewController
129144
}
130145
}
131146

147+
- (nullable id<UIViewControllerInteractiveTransitioning>) prepareForInteractiveTransition {
148+
Boolean isInteractive = false;
149+
150+
if (_interactiveTransition) {
151+
Boolean isInteractiveResponds = false;
152+
Boolean startWithInteractiveResponds = false;
153+
154+
if ([_interactiveTransition respondsToSelector:@selector(isInteractive:)]) {
155+
isInteractiveResponds = true;
156+
} else {
157+
return nil;
158+
}
159+
160+
if ([_interactiveTransition respondsToSelector:@selector(startWithInteractiveContext:)]) {
161+
startWithInteractiveResponds = true;
162+
} else {
163+
return nil;
164+
}
165+
166+
if(isInteractiveResponds && startWithInteractiveResponds) {
167+
isInteractive = [_interactiveTransition isInteractive:_context];
168+
if(isInteractive) {
169+
_interactiveContext = [[MDMViewControllerInteractiveTransitionContext alloc] initWithTransition:_context];
170+
171+
[_interactiveTransition startWithInteractiveContext:_interactiveContext];
172+
}
173+
}
174+
}
175+
176+
return isInteractive == false ? nil : [_interactiveContext getPercentIT];
177+
}
132178
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
#import "MDMTransition.h"
19+
#import "MDMTransitionContext.h"
20+
#import "MDMViewControllerTransitionContext.h"
21+
22+
@interface MDMViewControllerInteractiveTransitionContext : NSObject <MDMInteractiveTransitionContext>
23+
- (nonnull instancetype)initWithTransition:(nonnull id<MDMTransitionContext>)transitionContext;
24+
- (UIPercentDrivenInteractiveTransition* _Nonnull)getPercentIT;
25+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#import "MDMViewControllerInteractiveTransitionContext.h"
18+
19+
@implementation MDMViewControllerInteractiveTransitionContext {
20+
UIPercentDrivenInteractiveTransition *_percent;
21+
}
22+
23+
@synthesize transitionContext = _transitionContext;
24+
25+
- (nonnull instancetype)initWithTransition:(nonnull id<MDMTransitionContext>)transitionContext {
26+
self = [super init];
27+
if (self) {
28+
_percent = [[UIPercentDrivenInteractiveTransition alloc] init];
29+
_transitionContext = transitionContext;
30+
}
31+
return self;
32+
}
33+
34+
- (UIPercentDrivenInteractiveTransition *_Nonnull)getPercentIT {
35+
return _percent;
36+
}
37+
38+
- (void)updatePercent:(CGFloat)percent {
39+
[_percent updateInteractiveTransition:percent];
40+
}
41+
42+
- (void)finishInteractiveTransition {
43+
[_percent finishInteractiveTransition];
44+
}
45+
46+
- (void)cancelInteractiveTransition {
47+
[_percent cancelInteractiveTransition];
48+
}
49+
@end

src/private/MDMViewControllerTransitionContext.m

+12-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#import "MDMTransition.h"
2020

2121
@implementation MDMViewControllerTransitionContext {
22+
id<MDMTransition> _transition;
2223
id<UIViewControllerContextTransitioning> _transitionContext;
2324
UIPresentationController *_presentationController;
2425
}
@@ -27,6 +28,7 @@ @implementation MDMViewControllerTransitionContext {
2728
@synthesize sourceViewController = _sourceViewController;
2829
@synthesize backViewController = _backViewController;
2930
@synthesize foreViewController = _foreViewController;
31+
@synthesize wasCancelled = _wasCancelled;
3032

3133
- (nonnull instancetype)initWithTransition:(nonnull id<MDMTransition>)transition
3234
direction:(MDMTransitionDirection)direction
@@ -82,10 +84,17 @@ - (UIView *)containerView {
8284
}
8385

8486
- (void)transitionDidEnd {
85-
[_transitionContext completeTransition:true];
86-
87+
BOOL wasCanceled = [_transitionContext transitionWasCancelled];
88+
if(wasCanceled) {
89+
_wasCancelled = false;
90+
[_transitionContext completeTransition: false];
91+
} else {
92+
_wasCancelled = true;
93+
[_transitionContext completeTransition: true];
94+
}
95+
8796
_transition = nil;
88-
97+
8998
[_delegate transitionDidCompleteWithContext:self];
9099
}
91100

0 commit comments

Comments
 (0)