-
Notifications
You must be signed in to change notification settings - Fork 12
Add support for interactive transitioning #14
Add support for interactive transitioning #14
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #14 +/- ##
============================================
- Coverage 80.13% 64.46% -15.67%
============================================
Files 3 4 +1
Lines 146 197 +51
============================================
+ Hits 117 127 +10
- Misses 29 70 +41
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass at feedback.
} | ||
timer.resume() | ||
} | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create a new example and include this timer code there so that users can play with the demo more easily.
var i = 0.01 | ||
func start(withInteractiveContext context: InteractiveTransitionContext) { | ||
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main) | ||
timer.scheduleRepeating(deadline: .now(), interval: .milliseconds(10), leeway: .milliseconds(10)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember: transition instances are reused for both the present and dismiss transitions, so any instance variables need to be re-initialized before the transition begins. In this case, we need to remember to reset i to 0.01 when we start the interactive transition.
If we don't reset the i
value then the transition will immediately complete the dismissal transition.
examples/FadeExample.m
Outdated
}); | ||
dispatch_resume(timer); | ||
} | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above: let's create a new example that specifically demonstrates interactive transitioning.
src/MDMTransition.h
Outdated
@@ -34,6 +35,8 @@ NS_SWIFT_NAME(Transition) | |||
*/ | |||
- (void)startWithContext:(nonnull id<MDMTransitionContext>)context; | |||
|
|||
@optional | |||
- (void)startWithInteractiveContext:(nonnull id<MDMInteractiveTransitionContext>)context; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally prefer avoiding @optional
these days because it means the compiler won't enforce method signatures.
Instead, I suggest we add an MDMTransitionWithInteraction
protocol similar to how we've been building the other features.
src/MDMTransitionContext.h
Outdated
@@ -80,3 +80,9 @@ NS_SWIFT_NAME(TransitionContext) | |||
@property(nonatomic, strong, readonly, nonnull) UIView *containerView; | |||
|
|||
@end | |||
|
|||
NS_SWIFT_NAME(InteractiveTransitionContext) | |||
@protocol MDMInteractiveTransitionContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this conform to MDMTransitionContext?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made MDMInteractiveTransitionContext because this controls how much of the animation should be presented. The MDMTransitionContext controls what animation should be presented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means the interactive start
API won't have access to things like the container view, the transition's direction, or the fore/back view controller - is this intentional? I can imagine that someone might want to have access to those properties in order to be able to configure the interactive behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean someone changing the animation midway?
For example,
1 second (total) animation of view fading in. Around 0.5 seconds into the animation, user can also manipulate the size of view.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might want to parse gestural movement differently depending on whether the transition is moving forward or backward, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking in here again: were you able to try making this conform to MDMTransitionContext
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tried. I'll try it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I have to admit this doesn't make any sense to me.
So right now, I have
@property(nonatomic, readonly, nonnull) id<MDMTransitionContext> transitionContext;
to save the instance of MDMTransitionContext
. If I inherit it, all I am doing is adding wrappers around MDMTransitionContext
and I still have to save the instance so I can implement transitionDidEnd
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a checklist below, but in short you shouldn't have to save the transition context in any sense because we already have a transition context - you'll provide this same instance to both the transition and the interactive transition (i.e. the transition interaction controller).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like you want interactive transition and transition merged. So, I'll check if isInteractive
is implemented. If it's not implemented, I assume it's not interactive, if it is implemented, I'll call isInteractive
to determine if the direction (forward/backward) should be interactive.
|
||
if ([_transition respondsToSelector:@selector(startWithInteractiveContext:)]) { | ||
_interactiveContext = [[MDMViewControllerInteractiveTransitionContext alloc] initWithTransition: _transition]; | ||
[_transition startWithInteractiveContext:_interactiveContext]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we'd put the animated and interactive start
invocations alongside one another in the transition context instance. Is it possible to move this call there?
8cce24b
to
b9ea0c3
Compare
src/MDMTransitionContext.h
Outdated
@@ -80,3 +80,9 @@ NS_SWIFT_NAME(TransitionContext) | |||
@property(nonatomic, strong, readonly, nonnull) UIView *containerView; | |||
|
|||
@end | |||
|
|||
NS_SWIFT_NAME(InteractiveTransitionContext) | |||
@protocol MDMInteractiveTransitionContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking in here again: were you able to try making this conform to MDMTransitionContext
?
Am proposing the following changes to consolidate the code paths here (these affect public APIs which is why I'm suggesting we make these changes now before the code lands):
|
src/MDMTransition.h
Outdated
|
||
NS_SWIFT_NAME(InteractiveTransition) | ||
@protocol MDMInteractiveTransition <NSObject> | ||
- (Boolean)isInteractive:(nonnull id<MDMTransitionContext>)context; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BOOL
src/MDMTransitionController.h
Outdated
@@ -44,5 +45,5 @@ NS_SWIFT_NAME(TransitionController) | |||
This may be non-nil while a transition is active. | |||
*/ | |||
@property(nonatomic, strong, nullable, readonly) id<MDMTransition> activeTransition; | |||
|
|||
@property(nonatomic, strong, nullable) id<MDMInteractiveTransition> interactiveTransition; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This technically isn't a "transition" as much as an interaction controller for a transition. Can we consider renaming this to transitionInteractionController
?
@@ -31,4 +32,5 @@ | |||
@property(nonatomic, strong, readonly, nonnull) id<MDMTransitionController> mdm_transitionController | |||
NS_SWIFT_NAME(transitionController); | |||
|
|||
@property(nonatomic, strong, nullable) id<MDMInteractiveTransitionContext> interactiveTransitionContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to expose this if we store the variable on the transition controller.
transitionController.transition = CrossFade()
transitionController.transitionInteractionController = SwipeToDismiss()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the type for transitionInteractionController?
@@ -129,4 +144,35 @@ - (void)prepareForTransitionWithSourceViewController:(nullable UIViewController | |||
} | |||
} | |||
|
|||
- (nullable id<UIViewControllerInteractiveTransitioning>) prepareForInteractiveTransition { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this method would happen as a result of prepareForTransition
. We know that the animation callback is invoked first and therefor our transition context will be initialized, so we can return the percent-driven transition controller from our transition context.
3c1d297
to
f643cd5
Compare
#3