Original blog, reproduced please indicate the source
My stackflow.
Objective:
The default iOS presentViewController toggle animation is pushed from the bottom and disappears from the top of the roll. However, because the iOS system defaults to all transition contexts. And for a specific transition context, we can make better results.
Tips: The so-called transition context, which is the start view and end view of the transition, and the corresponding Viewcontroller
Target effect
The final effect
Preparatory work
First write a CollectionView , each cell is a picture, because the core of this article is how to transition, so CollectionView the part skipped. After writing it, that's the effect.
Click on a CollectionView cell to see a larger image, then click on the big picture to disappear
This initial project can be downloaded here
CSDN Download
How to implement a custom transition animation
After IOS 8, we can set up ViewController a transitioningDelegate proxy to handle transition animations.
Through the document, you can see transitioningDelegate is an implementation UIViewControllerTransitioningDelegate of the Protocol object, first look at this protocol, this article mainly uses the following two methods
- Animationcontrollerfordismissedcontroller
- Animationcontrollerforpresentedcontroller
The purpose of the two methods is to provide an UIViewControllerAnimatedTransitioning object that follows the agreement, and then the object to actually process the session. By name you can see that one is dealing with present and one is dealing with dismiss.
This article is designed to let ViewController you handle transitions, in didSelectItemAtIndexPath which the transition agent for the PVC is set
dvc.transitioningDelegate = self
Then write a extension to implement the Protocol
extension ViewController:UIViewControllerTransitioningDelegate{ UIViewController) -> UIViewControllerAnimatedTransitioning? { returnnil } UIViewControllerUIViewControllerUIViewController) -> UIViewControllerAnimatedTransitioning? { returnnil }}
At this point, when you run the project again, you will see that there is no change or the default transition mode. Because we have not yet provided the actual animation. When the two proxy methods above return nil, the system uses the default method
Implement Uiviewcontrolleranimatedtransitioning
Create a new file named Animator.swift, and then create a new class that handles present transitions (dismiss similar) to implement Uiviewcontrolleranimatedtransitioning protocol
class PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{}
At this point, the error does not implement the Protocol, then we add the protocol method, this time the Animator.swift as follows
import Foundationimport UIKitclass PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{ letduration=0.5//动画的时间 var=//点击Cell的frame func transitionDuration(transitionContext: UIViewControllerContextTransitioning?-> NSTimeInterval { returnduration } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { }}
A brief introduction to the Protocol method here
- Transitionduration, returns the time of the transition animation
- Animatetransition, the actual transition animation, through the parameter Transitioncontext (transition context) to get the fromview,toview,fromviewcontroller of the transition, Toviewcontroller.
The principle of transitions
- When the transition starts, it automatically adds the Fromview to the transition containview
- When the transition ends, the Fromview is automatically removed Containview
So, what the developers have to do is
- Add Toview to the transition Containview and define the initial position and state of the Toview
- Define the state of the transition at the end of Fromview and Toview
- Creating animations
Implementing the actual transition animation
Based on the above principles, we modify the actual animation
Func animatetransition (transitioncontext:uiviewcontrollercontexttransitioning) {Let Containview = TransitionConte Xt. Containerview() Let Toview = Transitioncontext. Viewforkey(Uitransitioncontexttoviewkey)! Let Finalframe = Toview. FrameLet XScale = Originframe. Size. Width/toview. Frame. Size. WidthLet Yscale = Originframe. Size. Height/toview. Frame. Size. HeightToview. Transform= Cgaffinetransformmakescale (XScale, Yscale) Toview. Center= Cgpointmake (Cgrectgetmidx (Originframe), Cgrectgetmidy (originframe)) Containview?. Addsubview(Toview) UIView. Animatewithduration(Duration, animations: {() VoidinchToview. Center= Cgpointmake (Cgrectgetmidx (Finalframe), Cgrectgetmidy (finalframe)) Toview. Transform= cgaffinetransformidentity}) {(finished), VoidinchTransitioncontext. Completetransition(True)} }
Then, in Viewcontroller.swfit, add a property
let presentAnimator = PresentAnimator()
ModifydidSelectItemAtIndexPath
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { let dvc = DetailViewController() dvc.image"image.jpg") dvc.transitioningDelegate = self let cell = collectionView.cellForItemAtIndexPath(indexPath) as! FullImageCell presentAnimator.originFrame = cell.convertRect(cell.imageview.frame, toView: nil) self.presentViewController(dvc, animated: true, completion: nil) }
Modifying proxy methods
UIViewControllerUIViewControllerUIViewController) -> UIViewControllerAnimatedTransitioning? { return presentAnimator }
This time the animated effect is like GIF
Similarly, add transition animations for dismiss
Add a new class to the Animator.swift
Class dismisssanimator:nsobject,uiviewcontrolleranimatedtransitioning{Let Duration =0.6var originframe = Cgrectzero func transitionduration (transitioncontext:uiviewcontrollercontexttransitioning?), N Stimeinterval {return Duration} func animatetransition (transitioncontext:uiviewcontrollercontexttransition ing) {Let Containview = Transitioncontext. Containerview() Let Toview = Transitioncontext. Viewforkey(Uitransitioncontexttoviewkey)! Collection View Let Fromview = Transitioncontext. Viewforkey(Uitransitioncontextfromviewkey)! Full-screen ImageView let XScale = Originframe. Size. Width/toview. Frame. Size. WidthLet Yscale = Originframe. Size. Height/toview. Frame. Size. HeightContainview?. Addsubview(Toview) Containview?. Bringsubviewtofront(Fromview) UIView. Animatewithduration(Duration, animations: {() VoidinchFromview. Center= Cgpointmake (Cgrectgetmidx (self. Originframe), Cgrectgetmidy (self. Originframe)) Fromview. Transform= Cgaffinetransformmakescale (XScale, Yscale)}) {(finished)-VoidinchTransitioncontext. Completetransition(True)} }}
Then, in Viewcontroller.swift, didSelectItemAtIndexPath set Presentanimator.frame next line to add
dismissAnimator.originFrame = cell.convertRect(cell.imageview.frame, toView: nil)
Where Dismissanimator is a property of Viewcontroller
let dismissAnimator = DismisssAnimator()
Then, in the proxy method, return
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return dismissAnimator; }
The final effect
Download of the Complete project
CSDN Download (a link will be up)
Customizing transition animations for Presentviewcontroller (Swift)