दिलचस्प पोस्ट
आईट्यून्स कनेक्ट एपीआई उपयोगकर्ता की भाषा को कैसे पता लगाया गया पाठ पता लगा सकता है? पायथन में जावास्क्रिप्ट पार्सर क्या जावा प्रतिबिंब का उपयोग करके नेस्टेड क्लास का एक उदाहरण बनाना संभव है? सर्वर एंड्रॉइड को छवियां अपलोड करना आईएसओ स्विफ्ट का इस्तेमाल करते हुए NSURL कनेक्शन बास में एक स्ट्रिंग से एक निश्चित उपसर्ग / प्रत्यय निकालें नोटपैड ++ क्या सभी छिपे हुए अक्षरों को दिखाता है? एंड्रॉइड संपर्क निष्कर्षण हायफन (-) चरित्र से शुरू होने वाली फाइल नाम के साथ मैं कैसे काम कर सकता हूं? Json.NET रूट नाम के साथ सीरियलआइज़ ऑब्जेक्ट एक्लिप्स लॉन्च के साथ "java.library.path" को देशी लाइब्रेरी कैसे जोड़ना है (ओवरराइड करने के बजाय) नेस्टेड सूची इंडेक्स जांचें कि संख्या कहीं भी या अजीब है या नहीं धागा को क्या मतलब है?

नेविगेशन आधारित ऐप में पुश और पॉप एनिमेशन को कैसे बदलना है

मेरे पास एक नेविगेशन आधारित अनुप्रयोग है और मैं पुश और पॉप एनिमेशन के एनीमेशन को बदलना चाहता हूं। मुझे यह कैसे करना है?

वेब के समाधान से एकत्रित समाधान "नेविगेशन आधारित ऐप में पुश और पॉप एनिमेशन को कैसे बदलना है"

मैंने निम्नलिखित किया और यह ठीक काम करता है .. और यह समझना आसान और आसान है ..

CATransition* transition = [CATransition animation]; transition.duration = 0.5; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade //transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom [self.navigationController.view.layer addAnimation:transition forKey:nil]; [[self navigationController] popViewControllerAnimated:NO]; 

और पुश के लिए यही बात ..


स्विफ्ट 3.0 संस्करण:

 let transition = CATransition() transition.duration = 0.5 transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.type = kCATransitionFade self.navigationController?.view.layer.add(transition, forKey: nil) _ = self.navigationController?.popToRootViewController(animated: false) 

इस तरह से मैंने हमेशा इस कार्य को पूरा करने में सफल रखा है।

पुश के लिए:

 MainView *nextView=[[MainView alloc] init]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.75]; [self.navigationController pushViewController:nextView animated:NO]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO]; [UIView commitAnimations]; [nextView release]; 

पॉप के लिए:

 [UIView beginAnimations:nil context:NULL]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.75]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO]; [UIView commitAnimations]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDelay:0.375]; [self.navigationController popViewControllerAnimated:NO]; [UIView commitAnimations]; 

मुझे अब भी इस से बहुत कुछ प्रतिक्रिया मिल रही है, इसलिए मैं एनीमेशन ब्लॉक का उपयोग करने के लिए इसे आगे बढ़ाना और अपडेट करने जा रहा हूं, जो कि ऐप्पल ऐप को ऐप्पलॉग करने का तरीका सुझाया गया है।

पुश के लिए:

 MainView *nextView = [[MainView alloc] init]; [UIView animateWithDuration:0.75 animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [self.navigationController pushViewController:nextView animated:NO]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO]; }]; 

पॉप के लिए:

 [UIView animateWithDuration:0.75 animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO]; }]; [self.navigationController popViewControllerAnimated:NO]; 

पुश के लिए

 CATransition *transition = [CATransition animation]; transition.duration = 0.3; transition.type = kCATransitionFade; //transition.subtype = kCATransitionFromTop; [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; [self.navigationController pushViewController:ViewControllerYouWantToPush animated:NO]; 

पॉप के लिए

 CATransition *transition = [CATransition animation]; transition.duration = 0.3; transition.type = kCATransitionFade; //transition.subtype = kCATransitionFromTop; [self.navigationController.view.layer addAnimation:transition forKey:kCATransition]; [self.navigationController popViewControllerAnimated:NO]; 

@ मग्नेस का उत्तर, केवल तब स्विफ्ट (2.0) के लिए

  let transition = CATransition() transition.duration = 0.5 transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.type = kCATransitionPush transition.subtype = kCATransitionFromTop self.navigationController!.view.layer.addAnimation(transition, forKey: nil) let writeView : WriteViewController = self.storyboard?.instantiateViewControllerWithIdentifier("WriteView") as! WriteViewController self.navigationController?.pushViewController(writeView, animated: false) 

कुछ sidenotes:

आप इसे prepareForSegue साथ भी कर सकते हैं, बस इसे तैयार करने के लिए prepareForSegue या चाहिए shouldPerformSegueWithIdentifier हालांकि , यह इसके में डिफ़ॉल्ट एनीमेशन भी रखेगा इसे ठीक करने के लिए आपको स्टोरीबोर्ड पर जाना होगा, सेग्यू पर क्लिक करें, और 'एनिमेट्स' बॉक्स को अनचेक करें लेकिन यह IOS 9.0 और इसके बाद के संस्करण के लिए आपके ऐप को सीमित करेगा (कम से कम जब मैंने इसे एक्सकोड 7 में किया था)।

जब एक सेगू में कर रहे हैं, तो पिछले दो पंक्तियों को इस प्रकार से बदला जाना चाहिए:

 self.navigationController?.popViewControllerAnimated(false) 

हालांकि मैं झूठा सेट करता हूं, यह किस तरह की उपेक्षा करता है

निजी कॉल्स का उपयोग करना एक बुरा विचार है क्योंकि ऐप्पल अब ऐसा ऐप स्वीकार नहीं करता है। शायद आप यह कोशिश कर सकते हैं:

 //Init Animation [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration: 0.50]; [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES]; //Create ViewController MyViewController *myVC = [[MyViewController alloc] initWith...]; [self.navigationController pushViewController:myVC animated:NO]; [myVC release]; //Start Animation [UIView commitAnimations]; 

याद रखें कि स्विफ्ट में , विस्तार निश्चित रूप से आपके दोस्त हैं!

 public extension UINavigationController { /** Pop current view controller to previous view controller. - parameter type: transition animation type. - parameter duration: transition animation duration. */ func pop(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) { self.addTransition(transitionType: type, duration: duration) self.popViewControllerAnimated(false) } /** Push a new view controller on the view controllers's stack. - parameter vc: view controller to push. - parameter type: transition animation type. - parameter duration: transition animation duration. */ func push(viewController vc: UIViewController, transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) { self.addTransition(transitionType: type, duration: duration) self.pushViewController(vc, animated: false) } private func addTransition(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) { let transition = CATransition() transition.duration = duration transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.type = type self.view.layer.addAnimation(transition, forKey: nil) } } 

वहाँ यूआईएवीएसी नियंत्रक डिलीगेट और यूआईवीआईयूआई नियंत्रकअनिर्मित हैंसंपादित करें आप चाहते हैं कुछ भी के लिए एनीमेशन बदल सकते हैं।

उदाहरण के लिए, यह वीसी के लिए ऊर्ध्वाधर पॉप एनीमेशन है:

 @objc class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { return 0.5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)! let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! let containerView = transitionContext.containerView() let bounds = UIScreen.mainScreen().bounds containerView!.insertSubview(toViewController.view, belowSubview: fromViewController.view) toViewController.view.alpha = 0.5 let finalFrameForVC = fromViewController.view.frame UIView.animateWithDuration(transitionDuration(transitionContext), animations: { fromViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.height) toViewController.view.alpha = 1.0 }, completion: { finished in transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) }) } 

}

और तब

 func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { if operation == .Pop { return PopAnimator() } return nil; } 

उपयोगी ट्यूटोरियल https://www.objc.io/issues/5-ios7/view-controller-transitions/

मैं हाल ही में कुछ इसी तरह की कोशिश कर रहा था। मैंने फैसला किया कि मुझे यूआईएवीएसीईंट्रोलर की स्लाइडिंग एनीमेशन पसंद नहीं है, लेकिन मैं भी ऐसा एनिमेशन नहीं करना चाहता था, जो कि यूआईवी्यूई आपको कर्ल या ऐसा कुछ भी पसंद करता है। जब मैं पुश या पॉप करता हूं तो मैं दृश्यों के बीच क्रॉस फैड करना चाहता था।

समस्या में इस तथ्य को शामिल किया गया है कि दृश्य वाकई मौजूदा एक के शीर्ष पर एक दृश्य को देखने या पॉप कर रहा है, इसलिए फीका काम नहीं करता है। मैं अपने नए दृश्य को लेने और इसे UIViewController के स्टैक पर वर्तमान शीर्ष दृश्य के लिए एक subview के रूप में शामिल करने के लिए शामिल समाधान मिला। मैं इसे 0 की एक अल्फा के साथ जोड़ता हूं, फिर एक क्रॉसफेड ​​करता हूं। जब एनीमेशन अनुक्रम खत्म हो जाता है, तो मैं इसे बिना एनिमेट किए हुए दृश्य पर स्टैक पर धक्का देता हूं। मैं फिर पुराने टॉपदृश्य पर वापस जाओ और सामान को साफ करें जो मैंने बदल दिया था।

इसकी तुलना में थोड़ा अधिक जटिल है, क्योंकि आपके पास नेविगेशन है कि आपको संक्रमण को सही बनाने के लिए समायोजित करना होगा। इसके अलावा, यदि आप किसी भी रोटेशन करते हैं, तो आपको फ़्रेम आकार को समायोजित करना होगा जैसे कि आप दृश्यों को उप-दृश्यों के रूप में जोड़ते हैं ताकि वे स्क्रीन पर सही तरीके से दिखाई दें। यहाँ कुछ कोड मैं इस्तेमाल किया है मैं UINavigationController subclassed और धक्का और पॉप तरीकों को ओवरराइड।

 -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { UIViewController *currentViewController = [self.viewControllers lastObject]; //if we don't have a current controller, we just do a normal push if(currentViewController == nil) { [super pushViewController:viewController animated:animated]; return; } //if no animation was requested, we can skip the cross fade if(!animation) { [super pushViewController:viewController animated:NO]; return; } //start the cross fade. This is a tricky thing. We basically add the new view //as a subview of the current view, and do a cross fade through alpha values. //then we push the new view on the stack without animating it, so it seemlessly is there. //Finally we remove the new view that was added as a subview to the current view. viewController.view.alpha = 0.0; //we need to hold onto this value, we'll be releasing it later NSString *title = [currentViewController.title retain]; //add the view as a subview of the current view [currentViewController.view addSubview:viewController.view]; [currentViewController.view bringSubviewToFront:viewController.view]; UIBarButtonItem *rButtonItem = currentViewController.navigationItem.rightBarButtonItem; UIBarButtonItem *lButtonItem = currentViewController.navigationItem.leftBarButtonItem; NSArray *array = nil; //if we have a right bar button, we need to add it to the array, if not, we will crash when we try and assign it //so leave it out of the array we are creating to pass as the context. I always have a left bar button, so I'm not checking to see if it is nil. Its a little sloppy, but you may want to be checking for the left BarButtonItem as well. if(rButtonItem != nil) array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,rButtonItem,nil]; else { array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,nil]; } //remove the right bar button for our transition [currentViewController.navigationItem setRightBarButtonItem:nil animated:YES]; //remove the left bar button and create a backbarbutton looking item //[currentViewController.navigationItem setLeftBarButtonItem:nil animated:NO]; //set the back button UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:title style:kButtonStyle target:self action:@selector(goBack)]; [currentViewController.navigationItem setLeftBarButtonItem:backButton animated:YES]; [viewController.navigationItem setLeftBarButtonItem:backButton animated:NO]; [backButton release]; [currentViewController setTitle:viewController.title]; [UIView beginAnimations:@"push view" context:array]; [UIView setAnimationDidStopSelector:@selector(animationForCrossFadePushDidStop:finished:context:)]; [UIView setAnimationDelegate:self]; [UIView setAnimationDuration:0.80]; [viewController.view setAlpha: 1.0]; [UIView commitAnimations]; } -(void)animationForCrossFadePushDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { UIViewController *c = [(NSArray*)context objectAtIndex:0]; UIViewController *n = [(NSArray*)context objectAtIndex:1]; NSString *title = [(NSArray *)context objectAtIndex:2]; UIBarButtonItem *l = [(NSArray *)context objectAtIndex:3]; UIBarButtonItem *r = nil; //not all views have a right bar button, if we look for it and it isn't in the context, //we'll crash out and not complete the method, but the program won't crash. //So, we need to check if it is there and skip it if it isn't. if([(NSArray *)context count] == 5) r = [(NSArray *)context objectAtIndex:4]; //Take the new view away from being a subview of the current view so when we go back to it //it won't be there anymore. [[[c.view subviews] lastObject] removeFromSuperview]; [c setTitle:title]; [title release]; //set the search button [c.navigationItem setLeftBarButtonItem:l animated:NO]; //set the next button if(r != nil) [c.navigationItem setRightBarButtonItem:r animated:NO]; [super pushViewController:n animated:NO]; } 

जैसा कि मैंने कोड में उल्लेख किया है, मेरे पास हमेशा एक बाएं बार बटन आइटम है, इसलिए मैं यह देखने की जांच नहीं करता कि क्या यह एरे में डालने से पहले कि मैं एनीमेशन प्रतिनिधि के लिए संदर्भ के रूप में पास करता हूँ। यदि आप ऐसा करते हैं, तो आप उस चेक को बना सकते हैं।

मैंने पाया समस्या यह थी कि यदि आप प्रतिनिधि विधि में बिल्कुल भी दुर्घटना करते हैं, तो यह प्रोग्राम को क्रैश नहीं करेगा। यह केवल प्रतिनिधि को पूरा करने से रोकता है, लेकिन आपको किसी प्रकार की चेतावनी नहीं मिलती।
इसलिए जब मैं उस प्रतिनिधि को नियमित रूप से सफाई में कर रहा था, तब से यह कुछ अजीब दृश्य व्यवहार पैदा कर रहा था क्योंकि यह सफाई खत्म नहीं हो रहा था।

मैंने बनाया बैक बटन "गोएबैक" विधि को कॉल करता है, और उस पद्धति में बस पॉप रूटीन को कॉल करता है

 -(void)goBack { [self popViewControllerAnimated:YES]; } 

इसके अलावा, यहां मेरा पॉप दिनचर्या है

 -(UIViewController *)popViewControllerAnimated:(BOOL)animated { //get the count for the number of viewControllers on the stack int viewCount = [[self viewControllers] count]; //get the top view controller on the stack UIViewController *topViewController = [self.viewControllers objectAtIndex:viewCount - 1]; //get the next viewController after the top one (this will be the new top one) UIViewController *newTopViewController = [self.viewControllers objectAtIndex:viewCount - 2]; //if no animation was requested, we can skip the cross fade if(!animated) { [super popViewControllerAnimated:NO]; return topViewController; } //start of the cross fade pop. A bit tricky. We need to add the new top controller //as a subview of the curent view controler with an alpha of 0. We then do a cross fade. //After that we pop the view controller off the stack without animating it. //Then the cleanup happens: if the view that was popped is not released, then we //need to remove the subview we added and change some titles back. newTopViewController.view.alpha = 0.0; [topViewController.view addSubview:newTopViewController.view]; [topViewController.view bringSubviewToFront:newTopViewController.view]; NSString *title = [topViewController.title retain]; UIBarButtonItem *lButtonItem = topViewController.navigationItem.leftBarButtonItem; UIBarButtonItem *rButtonItem = topViewController.navigationItem.rightBarButtonItem; //set the new buttons on top of the current controller from the new top controller if(newTopViewController.navigationItem.leftBarButtonItem != nil) { [topViewController.navigationItem setLeftBarButtonItem:newTopViewController.navigationItem.leftBarButtonItem animated:YES]; } if(newTopViewController.navigationItem.rightBarButtonItem != nil) { [topViewController.navigationItem setRightBarButtonItem:newTopViewController.navigationItem.rightBarButtonItem animated:YES]; } [topViewController setTitle:newTopViewController.title]; //[topViewController.navigationItem.leftBarButtonItem setTitle:newTopViewController.navigationItem.leftBarButtonItem.title]; NSArray *array = nil; if(rButtonItem != nil) array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,rButtonItem,nil]; else { array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,nil]; } [UIView beginAnimations:@"pop view" context:array]; [UIView setAnimationDidStopSelector:@selector(animationForCrossFadePopDidStop:finished:context:)]; [UIView setAnimationDelegate:self]; [UIView setAnimationDuration:0.80]; [newTopViewController.view setAlpha: 1.0]; [UIView commitAnimations]; return topViewController; } -(void)animationForCrossFadePopDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { UIViewController *c = [(NSArray *)context objectAtIndex:0]; //UIViewController *n = [(NSArray *)context objectAtIndex:1]; NSString *title = [(NSArray *)context objectAtIndex:1]; UIBarButtonItem *l = [(NSArray *)context objectAtIndex:2]; UIBarButtonItem *r = nil; //Not all views have a right bar button. If we look for one that isn't there // we'll crash out and not complete this method, but the program will continue. //So we need to check if it is therea nd skip it if it isn't. if([(NSArray *)context count] == 4) r = [(NSArray *)context objectAtIndex:3]; //pop the current view from the stack without animation [super popViewControllerAnimated:NO]; //if what was the current veiw controller is not nil, then lets correct the changes //we made to it. if(c != nil) { //remove the subview we added for the transition [[c.view.subviews lastObject] removeFromSuperview]; //reset the title we changed c.title = title; [title release]; //replace the left bar button that we changed [c.navigationItem setLeftBarButtonItem:l animated:NO]; //if we were passed a right bar button item, replace that one as well if(r != nil) [c.navigationItem setRightBarButtonItem:r animated:NO]; else { [c.navigationItem setRightBarButtonItem:nil animated:NO]; } } } 

तो इतना ही है। यदि आपको रोटेशन लागू करना है तो आपको कुछ अतिरिक्त कोड की आवश्यकता होगी। आपको अपने विचारों के फ्रेम आकार को सेट करने की आवश्यकता होगी कि आप उन्हें दिखाए जाने से पहले सबव्यूज़ के रूप में जोड़ते हैं, अन्यथा आप समस्याओं में चलेंगे, उन्मुखीकरण परिदृश्य होता है, लेकिन पिछली बार आपने पिछले दृश्य को देखा था यह चित्र था। तो, आप इसे एक उप दृश्य के रूप में जोड़ते हैं और इसे फीका करते हैं लेकिन यह चित्र के रूप में दिखाया जाता है, फिर जब हम एनीमेशन के बिना पॉपते हैं, वही दृश्य देखते हैं, लेकिन जो स्टैक में है, अब परिदृश्य है। पूरी बात थोड़ा दिखलाना दिखती है रोटेशन के सभी का कार्यान्वयन थोड़ा अलग है, इसलिए मैंने इसके लिए अपना कोड शामिल नहीं किया था।

आशा है कि यह कुछ लोगों को मदद करता है मैंने इस तरह कुछ के लिए सब कुछ देखा है और कुछ भी नहीं मिल सका। मुझे नहीं लगता कि यह सही जवाब है, लेकिन यह इस समय मेरे लिए वास्तविक रूप से काम कर रहा है।

चूंकि यह Google पर सबसे अच्छा परिणाम है, इसलिए मैंने सोचा कि मैं जो सोचता हूं वह सबसे समझदार तरीका है। जो iOS 7+ संक्रमण एपीआई का उपयोग करना है I मैंने इसे स्विफ्ट 3 के साथ आईओएस 10 के लिए कार्यान्वित किया

यदि आप UINavigationController उप-वर्ग बनाते हैं और UIViewControllerAnimatedTransitioning प्रोटोकॉल के अनुरूप होने वाले किसी क्लास का एक उदाहरण लौटाते हैं, तो इसे UINavigationController दो दृश्य नियंत्रकों के बीच एनिमेट करने के तरीके के साथ यह बहुत आसान है।

उदाहरण के लिए, मेरा UINavigationController उपवर्ग है:

 class NavigationController: UINavigationController { init() { super.init(nibName: nil, bundle: nil) delegate = self } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension NavigationController: UINavigationControllerDelegate { public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { return NavigationControllerAnimation(operation: operation) } } 

आप देख सकते हैं कि मैंने अपने लिए UINavigationControllerDelegate को सेट किया है, और अपने उप-क्लास पर एक एक्सटेंशन में मैं UINavigationControllerDelegate में विधि को लागू करता हूं जो आपको एक कस्टम एनीमेशन नियंत्रक (यानी, NavigationControllerAnimation नियंत्रकअनुमति) वापस करने की अनुमति देता है। यह कस्टम ऐनिमेशन नियंत्रक आपके लिए स्टॉक एनीमेशन को बदल देगा।

आप शायद सोच रहे हैं कि मैं ऑपरेशन में NavigationControllerAnimation उदाहरण को अपने प्रारंभकर्ता के द्वारा क्यों पास करता हूं। मैं ऐसा करता हूं ताकि NavigationControllerAnimation UIViewControllerAnimatedTransitioning कार्यान्वयन के कार्यान्वयन में UIViewControllerAnimatedTransitioning प्रोटोकॉल मुझे पता है कि ऑपरेशन क्या है (यानी, 'पुश' या 'पॉप')। यह जानने में मदद करता है कि मुझे किस प्रकार के एनीमेशन चाहिए। ज्यादातर समय, आप ऑपरेशन के आधार पर एक भिन्न एनीमेशन करना चाहते हैं।

बाकी सुंदर मानक है UIViewControllerAnimatedTransitioning प्रोटोकॉल में दो आवश्यक फ़ंक्शन लागू करें और आप की तरह चेतन करें:

 class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning { let operation: UINavigationControllerOperation init(operation: UINavigationControllerOperation) { self.operation = operation super.init() } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return } let containerView = transitionContext.containerView if operation == .push { // do your animation for push } else if operation == .pop { // do your animation for pop } } } 

यह याद रखना महत्वपूर्ण है, कि प्रत्येक अलग प्रकार के ऑपरेशन के लिए (यानी, 'पुश' या 'पॉप), देखने नियंत्रक से और अलग होगा जब आप एक पुश ऑपरेशन में हैं, नियंत्रक को देखने के लिए एक को धक्का दिया जाएगा। जब आप किसी पॉप ऑपरेशन में होते हैं, नियंत्रक को देखने के लिए वह एक होगा जिसे ट्रांज़िशन किया जा रहा है, और दृश्य नियंत्रक से वह पॉप होगा जो पॉप हो रहा है।

साथ ही, नियंत्रक to देखने के लिए संक्रमण के संदर्भ में containerView वीव के उपदृश्य के रूप में जोड़ा जाना चाहिए।

जब आपकी एनीमेशन पूरी होती है, तो आपको transitionContext.completeTransition(true) को कॉल करना होगा। यदि आप एक इंटरेक्टिव ट्रांजिशन कर रहे हैं, तो एनिमेशन के अंत में संक्रमण पूर्ण होने पर, आप को completeTransition(didComplete: Bool) करने के लिए completeTransition(didComplete: Bool) गया completeTransition(didComplete: Bool) को गतिशील रूप से वापस करना होगा।

आखिरकार ( वैकल्पिक पठन ), आप यह देखना चाहेंगे कि मैंने उस संक्रमण को कैसे किया जो मैंने काम कर रहा था। यह कोड थोड़ा और हैकी है और मैंने इसे बहुत तेज़ी से लिखा है इसलिए मैं यह महान एनीमेशन कोड नहीं कहूंगा, लेकिन यह अभी भी दिखाता है कि एनीमेशन भाग कैसे करना है।

मेरा वास्तव में एक सरल संक्रमण था; मैं एक ही एनीमेशन की नकल करना चाहता हूं जो कि यूआईएवीएजिएन्ट्रॉलर आम तौर पर करता है, परन्तु 'शीर्ष पृष्ठ पर एनीमेशन पर अगला पेज' के बजाय, मैं पुराने दृश्य नियंत्रक के 1: 1 एनीमेशन को एक ही समय के साथ नए दृश्य के रूप में लागू करना चाहता था नियंत्रक प्रकट होता है इसका दो दृश्य नियंत्रकों को बनाने का असर होता है जैसे कि वे एक दूसरे के लिए पिन किए जाते हैं

पुश ऑपरेशन के लिए, जिसने पहली बार toViewController -दृश्य toViewController के दृश्य को एक्स-अक्ष बंद स्क्रीन पर सेट करने की आवश्यकता है, इसे containerView origin.x रूप में जोड़कर, उस origin.x को शून्य पर सेट करके स्क्रीन पर एनिमेट करने की आवश्यकता है। उसी समय, मैं स्क्रीन से इसकी origin.x सेटिंग के द्वारा origin.x दृश्य को दूर करता origin.x :

 toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0) containerView.addSubview(toViewController.view) UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: [ UIViewAnimationOptions.curveEaseOut ], animations: { toViewController.view.frame = containerView.bounds fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0) }, completion: { (finished) in transitionContext.completeTransition(true) }) 

पॉप ऑपरेशन मूल रूप से व्युत्क्रम है। toViewController को toViewController के एक toViewController रूप में जोड़ें, और toViewController को दाईं ओर चेतन करें जैसा कि आप toViewController में बाएं से चेतन:

 containerView.addSubview(toViewController.view) UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: [ UIViewAnimationOptions.curveEaseOut ], animations: { fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0) toViewController.view.frame = containerView.bounds }, completion: { (finished) in transitionContext.completeTransition(true) }) 

पूरी स्विफ्ट फाइल के साथ एक सार है:

https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be

स्विफ्ट में मैंने ऐसा ही किया है:

पुश के लिए:

  UIView.animateWithDuration(0.75, animations: { () -> Void in UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut) self.navigationController!.pushViewController(nextView, animated: false) UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView: self.navigationController!.view!, cache: false) }) 

पॉप के लिए:

मैं वास्तव में ऊपर की कुछ प्रतिक्रियाओं के लिए थोड़ा अलग था – लेकिन जैसा कि मैं स्विफ्ट विकास के लिए नया हूँ, यह सही नहीं होगा। मैंने ओवरराइड viewWillDisappear:animated: है viewWillDisappear:animated: और इसमें पॉप कोड जोड़ा गया:

  UIView.animateWithDuration(0.75, animations: { () -> Void in UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut) UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.navigationController!.view, cache: false) }) super.viewWillDisappear(animated) 

प्रेरणा के रूप में iJordan के उत्तर का उपयोग करके, यूआईनेविज़न नियंत्रक पर एक श्रेणी को पूरे एक्शन कोड को प्रतिलिपि बनाने / चिपकाने के बजाय अपने ऐप का उपयोग करने के लिए क्यों न बनाएं?

UINavigationController + Animation.h

 @interface UINavigationController (Animation) - (void) pushViewControllerWithFlip:(UIViewController*) controller; - (void) popViewControllerWithFlip; @end 

UINavigationController + Animation.m

 @implementation UINavigationController (Animation) - (void) pushViewControllerWithFlip:(UIViewController *) controller { [UIView animateWithDuration:0.50 animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [self pushViewController:controller animated:NO]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO]; }]; } - (void) popViewControllerWithFlip { [UIView animateWithDuration:0.5 animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO]; }]; [self popViewControllerAnimated:NO]; } @end 

फिर बस यूआईएवीएजिएन्ट्रॉलर + एनीमेशन.h फ़ाइल आयात करें और इसे सामान्य रूप से कॉल करें:

 [self.navigationController pushViewControllerWithFlip:[[NewViewController alloc] init]]; [self.navigationController popViewControllerWithFlip]; 

हालांकि यहां सभी उत्तर महान हैं और अधिकांश काम बहुत अच्छी तरह से हैं, लेकिन थोड़ा सा आसान तरीका है जो एक ही प्रभाव को प्राप्त करता है …

पुश के लिए:

  NextViewController *nextViewController = [[NextViewController alloc] init]; // Shift the view to take the status bar into account CGRect frame = nextViewController.view.frame; frame.origin.y -= 20; frame.size.height += 20; nextViewController.view.frame = frame; [UIView transitionFromView:self.navigationController.topViewController.view toView:nextViewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) { [self.navigationController pushViewController:nextViewController animated:NO]; }]; 

पॉप के लिए:

  int numViewControllers = self.navigationController.viewControllers.count; UIView *nextView = [[self.navigationController.viewControllers objectAtIndex:numViewControllers - 2] view]; [UIView transitionFromView:self.navigationController.topViewController.view toView:nextView duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) { [self.navigationController popViewControllerAnimated:NO]; }];} 

मुझे किसी भी तरह से पता नहीं है कि आप संक्रमण एनीमेशन को सार्वजनिक रूप से बदल सकते हैं

यदि "वापस" बटन आवश्यक नहीं है, तो आपको "नीचे से धक्का" / "फ्लिप" / "फीका" / (≥3.2) "पृष्ठ कर्ल" बदलाव के लिए मोडल व्यू नियंत्रकों का उपयोग करना चाहिए


निजी तरफ, विधि- -pushViewController:animated: undocumented विधि को कॉल करता -pushViewController:transition:forceImmediate: तो उदाहरण के लिए यदि आप एक फ्लिप- -pushViewController:transition:forceImmediate: बाएं से सही संक्रमण चाहते हैं, तो आप उपयोग कर सकते हैं

 [navCtrler pushViewController:ctrler transition:10 forceImmediate:NO]; 

आप इस तरह "पॉप" संक्रमण को बदल नहीं सकते हैं, हालांकि।

कोड के बहुत कम लाइनों में इसे करने के लिए इस प्रश्न का उत्तर देखें This method allows you to animate a pseudo-"Push" of a new view controller any way you like, and when the animation is done it sets up the Navigation Controller just as if you had used the standard Push method. My example lets you animate either a slide-in from the left or from the right. Code repeated here for convenience:

 -(void) showVC:(UIViewController *) nextVC rightToLeft:(BOOL) rightToLeft { [self addChildViewController:neighbor]; CGRect offscreenFrame = self.view.frame; if(rightToLeft) { offscreenFrame.origin.x = offscreenFrame.size.width * -1.0; } else if(direction == MyClimbDirectionRight) { offscreenFrame.origin.x = offscreenFrame.size.width; } [[neighbor view] setFrame:offscreenFrame]; [self.view addSubview:[neighbor view]]; [neighbor didMoveToParentViewController:self]; [UIView animateWithDuration:0.5 animations:^{ [[neighbor view] setFrame:self.view.frame]; } completion:^(BOOL finished){ [neighbor willMoveToParentViewController:nil]; [neighbor.view removeFromSuperview]; [neighbor removeFromParentViewController]; [[self navigationController] pushViewController:neighbor animated:NO]; NSMutableArray *newStack = [[[self navigationController] viewControllers] mutableCopy]; [newStack removeObjectAtIndex:1]; //self, just below top [[self navigationController] setViewControllers:newStack]; }]; } 

Have a look at ADTransitionController , a drop in replacement for UINavigationController with custom transition animations (its API matches the API of UINavigationController) that we created at Applidium.

You can use different pre-defined animations for push and pop actions such as Swipe , Fade , Cube , Carrousel , Zoom and so on.

See my more detailed answer, using only public methods, here:

Prevent the animation when clicking "Back" button in a navigation bar?

…it's imperfect (it means re-implementing some of UINavigationController) – but it doesn't use any private methods, and it works.

From the sample app, check out this variation. https://github.com/mpospese/MPFoldTransition/

 #pragma mark - UINavigationController(MPFoldTransition) @implementation UINavigationController(MPFoldTransition) //- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated - (void)pushViewController:(UIViewController *)viewController foldStyle:(MPFoldStyle)style { [MPFoldTransition transitionFromViewController:[self visibleViewController] toViewController:viewController duration:[MPFoldTransition defaultDuration] style:style completion:^(BOOL finished) { [self pushViewController:viewController animated:NO]; } ]; } - (UIViewController *)popViewControllerWithFoldStyle:(MPFoldStyle)style { UIViewController *toController = [[self viewControllers] objectAtIndex:[[self viewControllers] count] - 2]; [MPFoldTransition transitionFromViewController:[self visibleViewController] toViewController:toController duration:[MPFoldTransition defaultDuration] style:style completion:^(BOOL finished) { [self popViewControllerAnimated:NO]; } ]; return toController; } 

महज प्रयोग करें:

 ViewController *viewController = [[ViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController]; navController.navigationBarHidden = YES; [self presentViewController:navController animated:YES completion: nil]; [viewController release]; [navController release]; 

Realising this is an old question. I still would like to post this answer, as I had some problems popping several viewControllers with the proposed answers. My solution is to subclass UINavigationController and override all the pop and push methods.

FlippingNavigationController.h

 @interface FlippingNavigationController : UINavigationController @end 

FlippingNavigationController.m:

 #import "FlippingNavigationController.h" #define FLIP_DURATION 0.5 @implementation FlippingNavigationController - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { [UIView transitionWithView:self.view duration:animated?FLIP_DURATION:0 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromRight animations:^{ [super pushViewController:viewController animated:NO]; } completion:nil]; } - (UIViewController *)popViewControllerAnimated:(BOOL)animated { return [[self popToViewController:[self.viewControllers[self.viewControllers.count - 2]] animated:animated] lastObject]; } - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated { return [self popToViewController:[self.viewControllers firstObject] animated:animated]; } - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated { __block NSArray* viewControllers = nil; [UIView transitionWithView:self.view duration:animated?FLIP_DURATION:0 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromLeft animations:^{ viewControllers = [super popToViewController:viewController animated:NO]; } completion:nil]; return viewControllers; } @end 

I found a mildly recursive way to do this that works for my purposes. I have an instance variable BOOL that I use to block the normal popping animation and substitute my own non-animated pop message. The variable is initially set to NO. When the back button is tapped, the delegate method sets it to YES and sends a new non-animated pop message to the nav bar, thereby calling the same delegate method again, this time with the variable set to YES. With the variable is set to YES, the delegate method sets it to NO and returns YES to allow the non-animated pop occur. After the second delegate call returns, we end up back in the first one, where NO is returned, blocking the original animated pop! It's actually not as messy as it sounds. My shouldPopItem method looks like this:

 - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { if ([[navigationBar items] indexOfObject:item] == 1) { [expandedStack restack]; } if (!progPop) { progPop = YES; [navBar popNavigationItemAnimated:NO]; return NO; } else { progPop = NO; return YES; } } 

मेरे लिये कार्य करता है।

You can now use UIView.transition . Note that animated:false . This works with any transition option, pop, push, or stack replace.

 if let nav = self.navigationController { UIView.transition(with:nav.view, duration:0.3, options:.transitionCrossDissolve, animations: { _ = nav.popViewController(animated:false) }, completion:nil) }