iOS Development--Circular transition animations

Source: Internet
Author: User

Objective

In a new app--ping, users can subscribe to topics they're interested in, and the app pushes the relevant article or paragraph to the user. The app uses a very cool animation effect when switching views, as shown in:

Now we're going to do that. In general, the knowledge points used are:
1. Using proxy uiviewcontrolleranimatedtransitioning to implement custom animations between controllers
2. Create a layer of a specific shape using Uishapelayer
3, with mask effect to achieve the switch of view
4, using gestures and uipercentdriveninteractivetransition to achieve a controllable process of interaction.

Structure Analysis of realization thought

First of all, the switching effect here is the transition between the controllers, and is based on Uinavigationcontoller, because we need to navigate the controller's proxy to achieve. After 8.0, Uinavigationcontroller provides a proxy uinavigationcontrollerdelegate allows us to control the pop, push process between the controller, there is a method in the agent:

UINavigationControllerUIViewControllerUIViewController) -> UIViewControllerAnimatedTransitioning?

The return value of this method is an object that implements the uiviewcontrolleranimatedtransitioning protocol, which is another protocol in our project. It can control the animation time, write the custom animation process, and recycle the resources after the animation is completed.

In general, what we need is:
1, two controllers for switching
2, a Uinavigationcontrollerdelegate object control view Controller switching process
3, a Uiviewcontrolleranimatedtransitioning object to provide specific animation

Functional analysis

When another controller is about to show the content, it can be seen that a circle appears first from the upper right corner, the circle is enlarged, the content to be displayed is in the circle, and the contents of the original controller are still outside the circle. During the animation, the circle zooms in, and as it grows, the new content is slowly coming out. In other words, the function of this circle is to show the range, outside the shielding range.

This is the best way to achieve this by masking layers, The mask attribute determines the occlusion process. Of course, mask needs a Calayer object, here also said, this process appears to be round, for the specific shape, cashapelayer can easily solve the problem.

Specific implementation

With the idea, the implementation is simple. To prepare two controllers first, the basic requirement is to provide a button that can be used for the view switch:

Here from left to right in turn is Uinavigationcontroller, Viewcontroller, Viewcontroller, the top right corner of the button (rounded effect) to switch, the picture is the location of the chaos is due to the use of auto layout, plus only one picture , too lazy to tune:]

The first step, the implementation of the animation
Since the exact process of the animation is implemented by the Uiviewcontrolleranimatedtransitioning object, we will create this object first. Uiviewcontrolleranimatedtransitioning is a protocol in which there are two required methods and an optional method:

func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeIntervalfunc animateTransition(transitionContext: UIViewControllerContextTransitioning)optional func animationEnded(transitionCompleted: Bool)

As stated above, we build a separate class, let the new class implement the protocol, and write these three methods:

Class Circletransitionanimator:nsobject, uiviewcontrolleranimatedtransitioning {//context contains Fromviewcontroller, Toviewcontroller, Containview etc.    //we Keep a reference here to get the context during the animationWeakvarTransitioncontext:uiviewcontrollercontexttransitioning?    //duration TimeFunc transitionduration (transitioncontext:uiviewcontrollercontexttransitioning) -Nstimeinterval {return 0.5}//animation ProgressFunc animatetransition (transitioncontext:uiviewcontrollercontexttransitioning) {//get the context         Self.Transitioncontext=Transitioncontext//get Other important variable        varContainview=Transitioncontext.Containerview ()varFromvc=Transitioncontext.Viewcontrollerforkey (Uitransitioncontextfromviewcontrollerkey) as ViewcontrollervarToVC=Transitioncontext.Viewcontrollerforkey (Uitransitioncontexttoviewcontrollerkey) as Viewcontroller//button Here means the button this controls the changing progress in Fromviewcontroller        //we'll let the circle start from button ' s center        varbutton=Fromvc.Button Containview.Addsubview (ToVC.View//calculate Some values         LetCirclepathinitial=Uibezierpath (Ovalinrect:button.Frame//just big Enough is OK, too. Because here we just need to make sure the mask can cover all view         LetExtremepoint=Cgpoint (X:button.Center.X, Y:button.Center.Y-ToVC.View.Bounds.Size.Height LetRadius=sqrt (extremepoint.X*Extremepoint.X+Extremepoint.Y*Extremepoint.Y LetCirclepathfinal=Uibezierpath (Ovalinrect:cgrectinset (button.Frame-radius,-radius))//create shape Layer         LetShapelayer=Cashapelayer () Shapelayer.Path=Circlepathfinal.Cgpath ToVC.View.Layer.Mask=Shapelayer//create animation and add it         LetMaskanimation=Cabasicanimation (keypath:"Path") maskanimation.Fromvalue=Circlepathinitial.Cgpath maskanimation.Tovalue=Circlepathfinal.Cgpath maskanimation.Duration =  Self.Transitionduration (Transitioncontext) maskanimation.Delegate=  SelfShapelayer.Addanimation (Maskanimation, Forkey:"Path")} override Func Animationdidstop (anim:caanimation!, finished Flag:bool) {//end the animation         Self.Transitioncontext?.Completetransition (! Self.Transitioncontext!.Transitionwascancelled ())//remove The mask at Fromviewcontroller         Self.Transitioncontext?.Viewcontrollerforkey (Uitransitioncontextfromviewcontrollerkey)?.View.Layer.Mask=NIL}}

This is explained in detail in the comments, where two controllers are obtained from the context, creating cashapelayer based on this, by setting the starting path (mainly the radius is different) and assigning a value to the animation's starting property to complete the process.

The second step, the control of the animation
Next we need to uinavigationcontrollerdelegate the object to control the animation done above, still create a new class, implement the Protocol, and write the relevant method:

class navigationcontrollerdelegate:NSObject,uinavigationcontrollerdelegate{func Navigationcontroller(navigationcontroller: uinavigationcontroller, animationcontrollerforoperation operation: uinavigationcontrolleroperation, fromviewcontroller fromvc:  Uiviewcontroller, toviewcontroller toVC: uiviewcontroller)-uiviewcontrolleranimatedtransitioning? {returnCircletransitionanimator()}}

The third step. Connection
Finally, we assign an object of this class to the delegate of the Controller (navigation controller). This process can be done in storyboard, dragging an object into the Uinavigationcontroller, changing the class to Navigationcontrollerdelegate, Then drag the delegate of the navigation controller onto the object.

Now you can see the effect, and it's similar to ping:

Gesture manipulation

So our animation is done. Next, let's get the button "wiped out".
With the popularity of gestures, we can use gestures to do a lot of things, and these processes are often controllable, and the typical example is a very hot drawer menu.
Now we add a pan gesture for Uinavigationcontroller, which lets the view switch effect be controlled by the user drag.
Uinavigationcontrollerdelegate provides a way to return an "interactive process":

func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?

Uiviewcontrollerinteractivetransitioning is a proxy, and uipercentdriveninteractivetransition is the class that iOS provides for us to implement this proxy. This class can be scaled to update the view switching process, directly complete the switch, cancel the switch ... Therefore, we first need an object of that class. Also, in Uinavigationcontrollerdelegate, we want to get a reference to Uinavigationcontroller, so declare two variables:

varweakvar navigationVC: UINavigationController?

To add a pan gesture:

    override func awakeFromNib() {        super.awakeFromNib()        let panGR: UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: Selector("handlePan:"))        self.navigationVC?.view.addGestureRecognizer(panGR)    }

The core is the gesture processing code, the idea is very simple, based on the user's sliding offset value to determine the percentage of switching:

Func Handlepan (recognizer:uipangesturerecognizer) {var transition = recognizer. Translationinview(Self. NAVIGATIONVC!. View) var progress = fabs (transition. x)/Self. NAVIGATIONVC!. View. Bounds. Size. WidthSwitch recognizer. State{case. Began: Self. Interactioncontroller= Uipercentdriveninteractivetransition () if self. NAVIGATIONVC?. Viewcontrollers. Count>1{Self. NAVIGATIONVC?. popviewcontrolleranimated(True)} else {self. NAVIGATIONVC!. Topviewcontroller. Performseguewithidentifier("Pushsegue", Sender:nil)} case. Changed: Self. Interactioncontroller?. Updateinteractivetransition(progress) case. Ended: If Fabs (recognizer. Velocityinview(recognizer. View). x) >0{Self. Interactioncontroller?. Finishinteractivetransition()} else {self. Interactioncontroller?. Cancelinteractivetransition()} Self. Interactioncontroller= Nil Default:self. Interactioncontroller?. Cancelinteractivetransition() Self. Interactioncontroller= nil}}

Finally, we return the Uipercentdriveninteractivetransition object we created in the proxy method:

    func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {        return self.interactionController    }

So the gesture is done, and the effect is good.

Resources

This article is an article on Raywenderlich.

Http://www.raywenderlich.com/86521/how-to-make-a-view-controller-transition-animation-like-in-the-ping-app

Summary of the study, part of the picture is also from the article. Thank you ~

iOS Development--Circular transition animations

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.