Update
2015.11.19 lots people says shut up and show me the code. Demo project
2019.02.21 Community Contributors' projects:
- Swift version by ostathnicky
- Xamarin version by Soan Saini
- SwipeableCards (Swift) by Serhii
This post is aiming at the topic of UIViewController transitions. The gif shows what we are going to do — present ViewController from ViewController by dragging.
What is it?
To be short, you can't actually drag a UIViewController
to anywhere.
What makes you feel UIViewController animate from here to there is UIViewControllerAnimatedTransitioning, interact with it according to gestures turns out to be misleading.
How to do it
Design philosophy
There is no two UIViewController
in together, instead there's only one UIViewController
at a time. When user begin drag on certain subview, present another view controller with custom UIViewControllerAnimatedTransitioning by custom UIPercentDrivenInteractiveTransition protocol.
Technical things
These two protocols are the foundation of customizing interactive UIViewController
transitions. In case you don't know yet, take a glance before starting.
1. UIViewControllerAnimatedTransitioning protocol
2. UIPercentDrivenInteractiveTransition protocol
Your UIViewController
implements UIViewControllerTransitioningDelegate protocol to tell which animator and interactor are gonna used by custom transitions.
Customize transitions
Animators
BaseAnimator
mustOverride()
is a marco took from stackoverflow Yar's answer, or you can use nicklockwood's solution MustOverride GitHub. You can leave it blank as well, what mustOverride()
does is throw an exception when we forget to override the method in subclasses.
BaseAnimator
do only one thing, it determine if it's presenting or dismissing and call the corresponding method.
MiniToLargeViewAnimator
The trick is initialY
property, as you can see, the UIViewController
which transition customized will starts from initialY
and ends at initialY
as well. initialY
is where our mini view located.
At the time user begin dragging, we present a new UIViewContrller
and customize our transitionContext
to make it looks like the same as last UIViewController
.
- (UIView *)fakeMiniView
returns fake subview
from last UIViewController
, you may either mock a new one or snapshot existing one, choosing a practice that fits with your use case.
Implement animators
Let's say we present NextViewController
from ExistViewController
.
In ExistViewController.m
we declare class extension and implements UIViewControllerTransitioningDelegate.
ExistViewController
From now, you got a customized transitions animator, and sets up by UIViewControllerTransitioningDelegate.
present UIViewController
You should see your customized transition works.
Transitions response to gesture
MiniToLargeViewInteractive
attachToViewController:withView:presentViewController:
is helper mehtod, encapsulate gesture bindings.
In ExistViewController
, create two Interactors of presenting and dismissing, implement interactionControllerForPresentation:
and interactionControllerForDismissal:
methods from UIViewControllerTransitioningDelegate.
ExistViewController
There's a BOOL
property disableInteractivePlayerTransitioning
indicates if we want to skip custom UIPercentDrivenInteractiveTransition
or not, if you want modal or dismiss ViewController directly, then set it to NO
.
That's it.
Feel free to comment.
Update
2015.11.19 lots people says shut up and show me the code. Demo project
2019.02.21 Community Contributors' projects:
- Swift version by ostathnicky
- Xamarin version by Soan Saini
- SwipeableCards (Swift) by Serhii