IOS7 new feature Viewcontroller transition Toggle (ii) Toggle animation for System View Controller container---Push pop present Dismis

Source: Internet
Author: User

@ Previous chapter, introduced the main IOS7 added API, you can find that they are not a dead method, Apple gives us developers are all protocol interface, so we can be very good alone to write a class, in the implementation of our various custom effects.

1. Let's take a look at the implementation Custom Animation classes for uiviewcontrolleranimatedtransitioning

/** * Custom Animation class * Implementation protocol------> @protocol uiviewcontrolleranimatedtransitioning * This interface is responsible for the specific content of the switch, that is, "what should happen in the switchover" */@interfa Ce mthcustomanimator:nsobject <UIViewControllerAnimatedTransitioning> @end @implementation mthcustomanimator/ /The system gives a toggle context, which takes time to return this switchover based on the context-(Nstimeinterval) Transitionduration: (id< uiviewcontrollercontexttransitioning>) transitioncontext{return 1.0;} The main way to complete the container transitions animation is to complete the UIView setting and animation of the switch in this method-(void) Animatetransition: (id< uiviewcontrollercontexttransitioning>) transitioncontext{//Can be seen as destination Viewcontroller Uiviewcontroller *to    Viewcontroller = [Transitioncontext Viewcontrollerforkey:uitransitioncontexttoviewcontrollerkey]; Can be seen as source viewcontroller uiviewcontroller *fromviewcontroller = [Transitioncontext viewcontrollerforkey:    Uitransitioncontextfromviewcontrollerkey];    Add Toview to the container [[Transitioncontext Containerview] addSubview:toViewController.view];    ToViewController.view.alpha = 0.0; [UIView AnimatewithDuration:[self Transitionduration:transitioncontext] animations:^{//animation has a lot of effects, this shows a left offset fromviewcontroller.v        Iew.transform = cgaffinetransformmaketranslation (-320, 0);    ToViewController.view.alpha = 1.0;        } completion:^ (BOOL finished) {fromViewController.view.transform = cgaffinetransformidentity; Declaring the transition over--remember, don't forget to call completetransition at the end of the transition: This method [Transitioncontext completetransition:![    Transitioncontext Transitionwascancelled]]; }];}
PS: From the two methods of the protocol, it can be seen that the above two methods must be implemented to require a transition context parameter, which is an object conforming to the uiviewcontrollercontexttransitioning protocol. Typically, when we use the system's class, the system framework provides us with the transition agent (transitioning Delegates), creates a transition context object for us, and passes it to the animation controller.
Mainviewcontroller@interface Mthmainviewcontroller () <uinavigationcontrollerdelegate, Uiviewcontrollertransitioningdelegate> @property (Nonatomic,strong) mthcustomanimator *customanimator; @property (Nonatomic,strong) Pdtransitionanimator *mintomaxanimator; @property (Nonatomic,strong) Mthnextviewcontroller *nextvc;//Interactive Controller ( Interaction Controllers) controls an interactive transition by complying with the Uiviewcontrollerinteractivetransitioning protocol. @property (Strong, nonatomic) uipercentdriveninteractivetransition* Interactioncontroller; @end @implementation mthmainviewcontroller-(ID) initwithnibname: (NSString *) Nibnameornil Bundle: (NSBundle *) nibbundleornil{self = [Super I    Nitwithnibname:nibnameornil Bundle:nibbundleornil]; if (self) {//Custom initialization} return to self;}    -(void) viewdidload{[Super Viewdidload];    Do any additional setup after loading the view.    Self.navigationItem.title = @ "Demo";    Self.view.backgroundColor = [Uicolor Yellowcolor]; Set proxy Self.navigationcontroller. delegate = self;    Set transition Animation self.customanimator = [[Mthcustomanimator alloc] init];    Self.mintomaxanimator = [Pdtransitionanimator new];    SELF.NEXTVC = [[Mthnextviewcontroller alloc] init];    Present proxy and custom settings _nextvc.transitioningdelegate = self;        _nextvc.modalpresentationstyle = Uimodalpresentationcustom;    Push UIButton *pushbutton = [UIButton Buttonwithtype:uibuttontypesystem];    Pushbutton.frame = CGRectMake (140, 200, 40, 40);    [Pushbutton settitle:@ "Push" forstate:uicontrolstatenormal];    [Pushbutton addtarget:self Action: @selector (push) forcontrolevents:uicontroleventtouchupinside];        [Self.view Addsubview:pushbutton];    Present UIButton *modalbutton = [UIButton Buttonwithtype:uibuttontypesystem];    Modalbutton.frame = CGRectMake (265, 500, 50, 50);    [Modalbutton settitle:@ "Modal" forstate:uicontrolstatenormal];    [Modalbutton addtarget:self Action: @selector (modal) forcontrolevents:uicontroleventtouchupinside]; [Self.view AddSubView:modalbutton]; Gestures for interactive operation uipangesturerecognizer *panrecognizer = [[Uipangesturerecognizer alloc] initwithtarget:self action: @selec    Tor (Didclickpangesturerecognizer:)]; [Self.navigationController.view Addgesturerecognizer:panrecognizer];} -(void) push{[Self.navigationcontroller PUSHVIEWCONTROLLER:_NEXTVC animated:yes];} -(void) modal{[self PRESENTVIEWCONTROLLER:_NEXTVC animated:yes completion:nil];} #pragma mark-uinavigationcontrollerdelegate iOS7 2 new methods//animation effects-(id<uiviewcontrolleranimatedtransitioning>) Navigationcontroller: (Uinavigationcontroller *) Navigationcontroller animationcontrollerforoperation: ( uinavigationcontrolleroperation) Operation Fromviewcontroller: (Uiviewcontroller *) Fromvc ToViewController: ( Uiviewcontroller *) tovc{/** * typedef ns_enum (Nsinteger, uinavigationcontrolleroperation) {* Uinavigatio     Ncontrolleroperationnone, * uinavigationcontrolleroperationpush, * uinavigationcontrolleroperationpop, *  };    */if (operation = = Uinavigationcontrolleroperationpush) {return self.customanimator;    }else{return nil; }}//Interaction-(ID <UIViewControllerInteractiveTransitioning>) Navigationcontroller: (uinavigationcontroller*) Navigationcontroller Interactioncontrollerforanimationcontroller: (ID <uiviewcontrolleranimate dtransitioning>) animationcontroller{/** * In non-interactive animation effects, the method returns nil * interactive transitions, self-understanding means that users can use their own actions (common: gesture) control, different from the system The default given push or pop (non-interactive) */return _interactioncontroller;} #pragma mark-transitioning Delegate (Modal)//first 2 for Animation-(id<uiviewcontrolleranimatedtransitioning>) Animationcontrollerforpresentedcontroller: (Uiviewcontroller *) presented Presentingcontroller: (UIViewController *)    Presenting Sourcecontroller: (Uiviewcontroller *) source{self.minToMaxAnimator.animationType = animationtypepresent; return _mintomaxanimator;} -(id<uiviewcontrolleranimatedtransitioning>) AnimationcontrollerfordismissedcontroLler: (Uiviewcontroller *) dismissed{self.minToMaxAnimator.animationType = Animationtypedismiss; return _mintomaxanimator;} After 2 for interaction-(ID <UIViewControllerInteractiveTransitioning>) Interactioncontrollerforpresentation: (ID < uiviewcontrolleranimatedtransitioning>) animator{return _interactioncontroller;} -(ID <UIViewControllerInteractiveTransitioning>) Interactioncontrollerfordismissal: (ID < uiviewcontrolleranimatedtransitioning>) animator{return nil;}
The non-interactive transitions that are implemented above mean that the user cannot cancel or control the progress switch in a way that is completely specified by the system. How do you implement interactive transitions:

Uipercentdriveninteractivetransition implements the class of the uiviewcontrollerinteractivetransitioning interface, You can use a percentage to control the process of interactive switching. We only need to tell the instance of the class the current percentage of states in gesture recognition, and it is very convenient for us to calculate the current UI rendering based on this percentage and the migration method we have previously set. Several important methods are as follows:
-(void) Updateinteractivetransition: (cgfloat) percentcomplete update percentage, which is generally calculated by the length of the gesture recognition, and then updated. In the following example, you will see a detailed usage
-(void) Cancelinteractivetransition report interactive cancellation, return to status before switchover
– (void) Finishinteractivetransition report interaction Complete, update to status after switchover

#pragma mark-the main implementation of gesture interaction--->uipercentdriveninteractivetransition-(void) Didclickpangesturerecognizer: (    uipangesturerecognizer*) recognizer{uiview* view = Self.view; if (recognizer.state = = Uigesturerecognizerstatebegan) {//Get gesture Touch Point coordinates cgpoint location = [Recognizer Locati        Oninview:view]; Judge, when the user slides from the right side, the next VC (according to the actual need is to push or launch) if (Location.x > Cgrectgetmidx (view.bounds) && Self.navigationc Ontroller.viewControllers.count = = 1) {Self.interactioncontroller = [[Uipercentdriveninteractivetransition allo            c] init];        [Self PRESENTVIEWCONTROLLER:_NEXTVC animated:yes completion:nil]; }} else if (recognizer.state = = uigesturerecognizerstatechanged) {//Get gesture offset on the view coordinates cgpoint translation        = [Recognizer Translationinview:view];        Calculates a percentage based on the distance the finger drags, and the animated effect of the toggle also goes with this percentage cgfloat distance = fabs (Translation.x/cgrectgetwidth (view.bounds)); The interactive controller controls the progress of the animation [self.interactionController Updateinteractivetransition:distance]; } else if (recognizer.state = = uigesturerecognizerstateended) {cgpoint translation = [Recognizer Translationinview        : view];        Calculates a percentage based on the distance the finger drags, and the animated effect of the toggle also goes with this percentage cgfloat distance = fabs (Translation.x/cgrectgetwidth (view.bounds));        Move more than half to force completion if (Distance > 0.5) {[Self.interactioncontroller finishinteractivetransition];        } else {[Self.interactioncontroller cancelinteractivetransition];    }//After the end must be set to nil Self.interactioncontroller = nil; }}
@ Finally, to share an animated effect: Similar to Flying Rabbit cloud transmission Viewcontroller Switch

@implementation pdtransitionanimator#define switch_time 1.2-(nstimeinterval) Transitionduration: (ID < uiviewcontrollercontexttransitioning>) Transitioncontext {return switch_time;} #define Button_width 50.f#define button_space 10.f-(void) Animatetransition: (ID < uiviewcontrollercontexttransitioning>) Transitioncontext {uiviewcontroller* Toviewcontroller = [    Transitioncontext Viewcontrollerforkey:uitransitioncontexttoviewcontrollerkey]; uiviewcontroller* Fromviewcontroller = [Transitioncontext viewcontrollerforkey:    Uitransitioncontextfromviewcontrollerkey];    UIView * Toview = Toviewcontroller.view;        UIView * Fromview = Fromviewcontroller.view; if (Self.animationtype = = Animationtypedismiss) {//This method can effectively intercept the currently displayed view into a new view. You can use this captured view for display. For example, maybe you just want to do it with one. Animation, after all, is too expensive to animate with the original view. Because it intercepts the existing content, this method can only reflect the current state information of the captured view, but not the information that is displayed after the captured view. However, anyway,        Calling this method will be more efficient than loading the view.        UIView * snap = [Toview Snapshotviewafterscreenupdates:yes]; [TranSitioncontext.containerview Addsubview:snap]; [Snap Setframe:cgrectmake ([UIScreen mainscreen].bounds.size.width-button_width-button_space, [UIScreen MainScreen]                . Bounds.size.height-button_width-button_space, Button_width, Button_width)]; [UIView animatewithduration:[self Transitionduration:transitioncontext] animations:^{[snap Setframe:[uiscreen        Mainscreen].bounds]; } completion:^ (BOOL finished) {[UIView animatewithduration:0.5 animations:^{[[Transitioncontex                T Containerview] Addsubview:toview];            Snap.alpha = 0;                } completion:^ (BOOL finished) {[snap Removefromsuperview]; [Transitioncontext completetransition:!            [Transitioncontext transitionwascancelled]];        }];    }];        } else {UIView * snap2 = [Toview snapshotviewafterscreenupdates:yes];        [Transitioncontext.containerview ADDSUBVIEW:SNAP2]; UIView * snap = [Fromview SnapshotvIewafterscreenupdates:yes];                [Transitioncontext.containerview Addsubview:snap]; [UIView animatewithduration:[self Transitionduration:transitioncontext] animations:^{[snap Setframe:cgrectmake ([UIScreen mainscreen].bounds.size.width-button_width-button_space+ (BUTTON_WIDTH/2), [UIScreen MainScreen].        Bounds.size.height-button_width-button_space + (BUTTON_WIDTH/2), 0, 0)];            } completion:^ (BOOL finished) {[UIView animatewithduration:0.5 animations:^{//snap.alpha = 0;                } completion:^ (BOOL finished) {[snap Removefromsuperview];                [Snap2 Removefromsuperview];                [[Transitioncontext Containerview] addsubview:toview]; Remember not to forget oh [transitioncontext completetransition:![            Transitioncontext Transitionwascancelled]];        }];            }]; }}
@ which,snapshotviewafterscreenupdates method of interpretation, I do not very understand, anyway, the primary will be used on the line, you can also refer to the following analysis:

Before IOS7, getting a snapshot of a uiview has the following steps: First create a uigraphics image context, then render the view's layer to that context, get an image, finally close the image context, and display the image in Uiimageview. Now we just need one line of code to complete the above steps:

[View Snapshotviewafterscreenupdates:no];
This method makes a copy of the UIView, which is especially handy if we want the view to save its present appearance before the animation is performed, for later use (the view may be obscured by the views in the animation or some other change occurs).
The Afterupdates parameter indicates whether to get the snapshot after all effects are applied on the view. For example, if the parameter is no, you get a snapshot of the view's current state immediately, whereas the following code can only get a blank snapshot:
[View Snapshotviewafterscreenupdates:yes];
[View setalpha:0.0];
Since we set the Afterupdates parameter to Yes, and the view's transparency value is set to 0, the method will take a snapshot after the setting is applied to the view, and the screen is empty. The other is ... You can take a snapshot of the snapshot ... Continue snapshot ...

Finally, the main code has been given, the complete code I have uploaded as a resource, we have the intention to download down to see (alas, the main is CSDN not support GIF dynamic map, good egg pain, friends in the blog Park blog Support, but I do not like the style of blog Park, It seems that the future of a domain name blog is king, follow-up I will also put some of my code to share on GitHub)
@ Reprint Please specify, turn from [email protected] confused small book

IOS7 new feature Viewcontroller transition Toggle (ii) Toggle animation for System View Controller container---Push pop present Dismis

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.