[iOS] let’s solve all the problems in the navigation bar once and for all

Update: finally, the so-called “ultimate solution”, which has been used before its own project, has been shared and found that some areas need to be improved. However, the general idea is constant, so if necessary, the article will not make a drastic change. The final code should be at the end of the text GitHub address, and also welcome to provide Bug


Some time ago, I changed my job, the company project was relatively tight, and I didn’t have time to update the article. Now I’m free. I need to write an article to make up for my shame.
today, let’s focus on the return of the navigation bar, including solutions to all kinds of problems.

The return button and return mode of the system default navigation bar

By default, the navigation bar returns the same length as the button

The [iOS] let's solve all the problems in the navigation bar once and for all
navigation bar defaults to the return button

The return button in the upper left corner of the navigation bar, whose text defaults to the title of the previous ViewController. If the last ViewController has no title, it is Back (the Chinese context is “return”).

By default, the click, return, and sliding interactions returned by the navigation bar are as follows

The [iOS] let's solve all the problems in the navigation bar once and for all
default navigation bar interacts with each other

These things do not require any setting and operation, so there is no other area to explain.

Customize the return button in the upper left corner

Most of the time, we need to customize the return button at the top left corner of the product, although it’s not difficult for most developers, but there are still several issues worth noting.

Replace the return button in the upper left corner

Replace the return button is very simple, just need to create a UIBarButtonItem in ViewController and a picture, and the button to add the corresponding click event, the code is as follows

- (void) viewDidLoad {[super viewDidLoad]; Do any additional setup after loading / the view. UIButton * leftBtn buttonWithType:UIButtonTypeSystem] = [UIButton; leftBtn.frame = CGRectMake (0, 0, 25,25); [leftBtn setBackgroundImage:[UIImage imageNamed:@ nav_back forState:UIControlStateNormal] [leftBtn addTarget:self]; action:@selector (leftBarBtnClicked:) forControlEvents:UIControlEventTouchUpInside] [[UIBarButtonItem alloc]; self.navigationItem.leftBarButtonItem = initWithCustomView:leftBtn];} - (void (leftBarBtnClicked:) UIButton * BTN [self.navigationController) {popViewControllerAnimated:YES]};

Let’s take a look at the effect

[iOS] let's solve all the problems in the navigation bar once and for all
replaces the return button
Adjust button position

We can see that the buttons above are a little bit right, so what should we do if we want to adjust the position of the button? Setting Frame is obviously not going to work because the NavigationItem on the navigation bar is a special View, and we can’t adjust the left and right buttons by simply adjusting the Frame. But in Apple’s UIButtonBarItem, there is a control called UIBarButtonSystemItemFixedSpace, and with it we can easily adjust the location of the return button. The specific methods of use are as follows

/ / create the back button UIButton * leftBtn = [UIButton buttonWithType:UIButtonTypeSystem]; leftBtn.frame = CGRectMake (0, 0, 25,25); [leftBtn setBackgroundImage:[UIImage imageNamed:@ icon_back forState:UIControlStateNormal] [leftBtn addTarget:self]; action:@selector (leftBarBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem * leftBarBtn = [[UIBarButtonItem alloc]initWithCustomView:leftBtn]; UIBarButtonSystemItemFixedSpace UIBarButtonItem; / / create * spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; / / the width to negative spaceItem.width = -15; / / BarButtonItem two is returned to the NavigationItem self.navigationItem.leftBarButtonItems = @[spaceItem, left BarBtn];

Let’s take a look at the effect

[iOS] let's solve all the problems in the navigation bar once and for all
adjusts the back button position

As you can see, our return button is close to the edge of the screen.

This method also applies to adjusting the buttons on the right side of the navigation bar

Move the slider back into effect

If you use the custom button to replace the system default return button, there will be a slip back gesture failure. The solution is simple, just add the interactivePopGestureRecognizer of the delegate in the navigation bar.
first adds the UIGestureRecognizerDelegate protocol to the ViewContoller

Then set the proxy

Self.navigationController.interactivePopGestureRecognizer.delegate = self;

At this point, we have replaced the return button as our custom button, and made the slip return to effect. Next, let’s continue to address the interaction problem.

Full screen sliding back

This is a very common demand, online solutions are also many, here I used to paste the method here. For reference only,
implements full screen sliding back. Just add UIGestureRecognizerDelegate to the navigation bar in the navigation bar, and write the following code in ViewDidLoad

Get / / target system comes with sliding gestures object ID target = self.interactivePopGestureRecognizer.delegate; / / create a full screen slide gesture, call the action method of the target system comes with sliding gestures UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector (handleNavigationTransition:)]; / / set gesture agent, intercept gestures trigger pan.delegate = self; / / to the navigation controller view to add full screen slide gestures [self.view addGestureRecognizer:pan]; / / self.interactivePopGestureRecognizer.enabled = NO with sliding gestures since the prohibition of the use of the system;

Let’s take a look at the effect (note the mouse position)

[iOS] let's solve all the problems in the navigation bar once and for all
full screen sliding back.Gif


The principle of this method is very simple, in fact, is to customize a full screen sliding gesture, and set the sliding event to system sliding events, and then disable the system sliding gesture can. HandleNavigationTransition is the system sliding method, although the system does not provide the interface, but we can find this method through runtime, so you can call directly. Two, do not worry about what private API and other issues, apple if the method name to determine whether the use of private API, then you have to accidentally hurt how many App?.

“Ultimate solution” for NavigationBar switching animation”

This part of the text code is more, do not want to see so many nonsense students, please turn directly to the end of the text with a download address, after the introduction of the project, the inheritance can be effective.

After changing the navigation bar style and achieving full screen sliding back, we had a pretty good navigation bar. But we are still at the sliding switch system comes with the animation, if encountered before a NavigationBar interface is transparent or after two Bar of different colors, the gradual animation looks not very friendly, especially after the current two interface one interface NavigationBar is transparent or hidden, its effect is more is too horrible to look at.

This problem, in fact, a lot of App, such as Tmall, the United States, and so on, through a “whole return” effect to solve this problem. Effect is as follows:

[iOS] let's solve all the problems in the navigation bar once and for all
whole slide back

This solution is independent of the two NavigationBar, so it can be a relatively perfect solution to the various Bug in the slide switch of the navigation bar.
next, let’s see how to implement this effect.

Basic principle

With my personal knowledge, there are three basic ideas for achieving this effect:

Using the setNavigationBarHidden: animated: method with UINavigationController to achieve, each push or pop, is hidden in the current controller in viewWillDisappear:, set the navigation bar displayed on the controller to jump in viewWillAppear. Before each Push, screenshots of the current page are saved to the array. When Pop is taken, the last element of the array is displayed. After the end of the slide, the system Pop method is called and the last screenshot is deleted. After using iOS 7, the open UIViewControllerAnimatedTransitioning protocol is implemented to customize the navigation bar, transitions, animations, and interactions.

The above three methods, one method is very complicated, and there will be many inexplicable BUG, direct pass.

In iOS interaction, push is triggered by the click event of a button or the View event of tap, while pop may be triggered by events or triggered by right hand gestures. Therefore, we will be that we want to achieve animation effects for interactive effects and no interaction effect of the two, we will use the following methods 2 and 3 provide ideas, implement the two animation effect, so it can more perfectly solve the problem of Push and Pop.

Interactive animation effects

Prepare arrays and gestures that need to be used
#define ScreenWidth [UIScreen mainScreen].bounds.size.width #define ScreenHeight [UIScreen mainScreen].bounds.size.height @interface LTNavigationController (<); UIGestureRecognizerDelegate> @property (strong, nonatomic) UIImageView * screenshotImgView; @property (strong, nonatomic) UIView * coverView; @property (strong, nonatomic) NSMutableArray * screenshotImgs (strong, nonatomic); @property UIPanGestureRecognizer *panGestureRec; @end @implementation LTNavigationController (void) {viewDidLoad [super viewDidLoad] Do any additional setup after; / / loading / / the view. 1, create a Pan gesture recognizer, and bound _panGestureRec = [[UIScreenEdgePanGestureRecognizer alloc]initWithTarget:self action:@selector monitoring method (panGestureRec:); _panGestureRec.e Dges = UIRectEdgeLeft; / / navigation controller view to add the Pan gesture recognizer [self.view addGestureRecognizer:_panGestureRec]; / / create 2 screenshots of the ImageView _screenshotImgView = [[UIImageView alloc] init]; / / APP frame is included in the status bar height frame _screenshotImgView.frame = CGRectMake (0, 0, ScreenWidth, ScreenHeight); / / create 3 screenshot above black translucent mask _coverView = [[UIView alloc] init]; / / frame is a screenshot of the mask frame _coverView.frame = _screenshotImgView.frame; _coverView.backgroundColor = [UIColor / black mask for blackColor]; / / the 4 store all the screenshots of _screenshotImgs = [NSMutableArray array array];}
The corresponding event of gesture
The method of gesture / response (void) panGestureRec: (UIPanGestureRecognizer * panGestureRec) {/ / if the current display controller is the root controller, don't need to do any switching animation, returns if (self.visibleViewController = = self.viewControllers[0] return); / / determine the various stages of the switch pan gesture (panGestureRec.state) {case UIGestureRecognizerStateBegan: / / to drag the stage [self dragBegin]; break case UIGestureRecognizerStateEnded:; / / end stage [self dragEnd] break drag; default:; / / [self dragging:panGestureRec] break was towing stage; #pragma mark;}} drag, add pictures and mask - (void) dragBegin {/ / key, the beginning of each gesture Pan When to add ImageView and cover to cover the screenshots in window [self.view.window insertSubview:_screenshotImgView atIndex:0]; [self.view.window insertSubview:_coverView aboveSubview:_screenshotImgView]; / / and let imgView show the last screenshot in the array (the latest) a screenshot of _screenshotImgView.image [_screenshotImgs = lastObject]; //_screenshotImgView.transform = CGAffineTransformMakeTranslation (ScreenWidth, 0);} / / default will become a transparent mask the initial transparency (total black) #define kDefaultAlpha 0.6 / / when the distance of the drag, accounted for the total width of the screen high 3/4, let ImageView display completely covering #define kTargetTranslateScale 0.75 #pragma mark completely disappeared is dragging, the essence of animation, displacement and transparency change - (void) dragging: (UIPanG EstureRecognizer * pan) {/ / get your finger to drag the displacement CGFloat offsetX = [pan translationInView:self.view].x; / / view / / make the shift to move the whole Navigation view if (offsetX > 0) {self.view.transform = CGAffineTransformMakeTranslation (offsetX, 0);} / / finger dragging displacement calculation of the current total wide screen accounted for a high proportion, while the proportion of at 3/4, let ImageView display completely cover the complete disappearance of double currentTranslateScaleX if (offsetX = offsetX/self.view.frame.size.width; < ScreenWidth) {CGAffineTransformMakeTranslation (_screenshotImgView.transform = (offsetX - ScreenWidth) * 0.6, 0);} / / let transparency cover change, until reduced to 0, let the mask is completely transparent, the default (proportional current balance ratio / target balance ratio) * default The ratio of double = kDefaultAlpha - alpha (currentTranslateScaleX/kTargetTranslateScale) * kDefaultAlpha; _coverView.alpha = Alpha;} #pragma mark end drag, drag the distance for the corresponding judgment at the end, and the pictures and mask up from the parent control division (void) dragEnd distance CGFloat {/ / remove the mobile translateX = self.view.transform.tx; / / remove the width of CGFloat width if (translateX = self.view.frame.size.width; < = 40;) {/ / if the finger moving distance is less than half of the screen, move it to the left (back) [UIView animateWithDuration:0.3 animations:^{/ / view is an important ~ ~ let right back return, as long as the empty transform can do self.view.transform = CGAffineTransformIdentity; / / imageView to restore the default size of transla Tion _screenshotImgView.transform = CGAffineTransformMakeTranslation (-ScreenWidth, 0); / / to cover the transparency of restore the default alpha 1 _coverView.alpha = kDefaultAlpha;} completion:^ (BOOL finished) {/ / an animation, after the completion of all the time to remember to remove two view, the next began to drag, and then added [_screenshotImgView removeFromSuperview]; [_coverView removeFromSuperview];}];} else {/ / if the finger moving distance has more than half of the screen, then move to the right end of the [UIView animateWithDuration:0.3 animations:^{/ let be the right, the right to screen the view completely, but also remember to clear the view transform self.view.transform (WI = CGAffineTransformMakeTranslation DTH, 0); / / imageView = CGAffineTransformMakeTranslation displacement reduction of _screenshotImgView.transform (0, 0); / / to cover the alpha to 0, become completely transparent _coverView.alpha = 0;} completion:^ (BOOL finished) {/ / view is important ~ ~ let the shift to the right side of the screen completely, after the end, remember to clear the view transform, can be a problem or the next start again drag, because view transform did not return to zero self.view.transform = CGAffineTransformIdentity; / / remove two view, the next began to drag, and then add back [_screenshotImgView removeFromSuperview]; [_coverView removeFromSuperview]; / / perform normal Pop operation: remove the top of the stack controller, let a controller become a real guide Air controller stack controller [self popViewControllerAnimated:NO];}];}


Screenshot to save function, and screenshot in front of Push
- (void) screenShot {/ / will be a screenshot of the view, the root window view UIViewController controller *beyondVC = self.view.window.rootViewController; / / CGSize background picture total size size = beyondVC.view.frame.size; / / open context, using the parameters after the cut out of the original (YES 0 high quality UIGraphicsBeginImageContextWithOptions (size), YES, 0); / / CGRect = CGRectMake to rect rectangular clipping (0, 0, ScreenWidth, ScreenHeight); / / Note: iOS7 renderInContext: drawViewHierarchyInRect:afterScreenUpdates: [beyondVC.view drawViewHierarchyInRect:rect afterScreenUpdates:NO] by substitution; / / from the context, remove the UIImage UIImage *snapshot (= UIGraphicsGetImageFromCurrentImageContext); / / add a picture to a picture array (s good if interception Napshot) {[_screenshotImgs addObject:snapshot];} / / remember, the end of the context (the current bitmap graphics context based on the removal of the top of the stack (UIGraphicsEndImageContext));} - (void) pushViewController: (UIViewController *) viewController animated: (BOOL animated) {/ / have time controller in the navigation controller only need screenshots of if (self.viewControllers.count > = 1) {/ / call custom method, using the context screenshots of [self screenShot];} / / screenshot after the push [super pushViewController:viewController method call the parent class animated:YES];}
Rewrite the commonly used pop methods

At the beginning of the basic principle, we said pop to delete the last screenshot, to ensure that the last screenshot in the array is a controller, but in many cases we may call the popToViewController: method of the animated: navigation bar or popToRootViewControllerAnimated: to return, in this case, we may not delete screenshot, so we need to override the Pop method respectively, to determine how much we want to delete the picture, the code as follows

- (UIViewController) popViewControllerAnimated: (BOOL) animated return [super popViewControllerAnimated:animated] {[_screenshotImgs removeLastObject];} - (NSArray< UIViewController; *> *) popToViewController: (* UIViewController) viewController animated: (BOOL animated) {for (NSInteger I = self.viewControllers.count - 1; I 0; > i--) {if (viewController = = self.viewControllers[i]) {break [_screenshotImgs removeLastObject];};}} - return [super popToViewController:viewController animated:animated] (NSArray< UIViewController; *> *) popToRootViewControllerAnimated: (BOOL) animated return [super popToRootViewControllerAnimated:animated] {[_screenshotImgs removeAllObjects];};
The controller specified in shielding gesture

In the code above, we use side slip gestures and set the corresponding area to the left of the screen.
is not a full screen slide, because sometimes in full screen slide gestures and other gesture conflict, if the conflict is our custom gestures, natural good solution, but if the system is left hand gestures, such as TableView sliding menu operation, this thing is very awful.
but if we have to do full screen sliding gestures, we can make some minor modifications to the code, masking gestures in some of the controls.

First, add a list of disabled lists to the navigation bar and configure them

... @property (nonatomic, copy) NSArray * forbiddenArray;... - (void) viewDidLoad {[super viewDidLoad]; / / / / the original code... Will disable gestures after Push, according to the conditions of self.panGestureRec.enabled = enable / / open will need to disable the gesture controller class name added to the array of self.forbiddenArray @[@ = "SCViewController", "@ ManageAddressViewController"];} - (void) pushViewController: (UIViewController *) viewController animated: (BOOL animated) {/ / in the specified controller is disabled in the gesture return BOOL enable = YES to solve the sliding gesture and some gestures conflict; for (NSString * string in self.forbiddenArray * className) {NSString = NSStringFromClass ([viewController class] if isEqualToString:className] ([string);) {enable = NO;}} Self.panGestureRec.enabled = enable; / / the original code...} - (UIViewController *) popViewControllerAnimated: animated count (BOOL) {NSInteger = self.viewControllers.count; className = NSString * nil; if (count = > className = 2) {NSStringFromClass ([self.viewControllers[count -2] class]);} BOOL enable = YES; for (NSString * string in self.forbiddenArray) {if ([string isEqualToString:className]) {enable}} = NO; self.panGestureRec.enabled = enable; / / return [super popViewControllerAnimated:animated] the original code...};

Here, we have completed the interactive switch animation, the effect is the same as the beginning, no screenshots. Next, we’ll work on another big Boss- non interactive animation

Implement non interactive animation effects

theoretical basis

Here we are going to use the UIViewControllerAnimatedTransitioning we mentioned before. Because of the limited space, here no longer introduce basic knowledge of this part, we can move the two blog to do a preliminary understanding

Say goodbye to the traditional animation of UINavigationController – Custom
7 iOS: custom navigation, transitions, animations, and more

Realization principle

Note: FromVC stands for the vanishing view controller, and ToVC represents the view controller to be displayed

The effect we want to achieve: when
Push, FromVC moves to the left, ToVC appears from the right side of the screen, follows the FromVC left shift until the FromVC disappears, and at this point the ToVC is just fully displayed on the screen. At
Pop, FromVC moves to the right, and ToVC appears from the edge of the screen, follows FromVC, moves right until FromVC disappears, and at this point the ToVC is fully displayed on the screen

When implemented, we still need to Push Pop and
discussed separately first and 1 interactive animation, each Push on the screen and save the screenshot, Pop again but not save
2 Pop when the interception of the pictures as a FromVC display, the Push interface to the interception of the pictures as ToVC display
3 and two pictures on the displacement of animation, animation after removing two pictures

Then, when Push
1.Push, first screen the current screen.
2. saves the captured pictures and makes them easy to use when Pop comes back and saves the picture as a Push for this FromVC.
3 to obtain the current navigation controller, adjust the displacement parameters in its Transform properties as the ToVC display
4 on the screenshot and navigation bar to do directly after the end of displacement, remove animation screenshots

Why do you move the navigation bar? First of all, in the Push before the end, we can not know what is the specific ToVC, screen capture method system is incapable of action for not loaded out of View, snapshotViewAfterScreenUpdates: and UIView methods is unable with the navigation bar together is mapped to a new View, so the visual effect is very poor.
is just at the time of Pop, in order to achieve the desired animation, to two picture shows the need to put the navigation bar on the View in Push when we get directly to the navigation bar View to make a transformation of radiation, of course, this also means that, when we Push the screenshot no longer in the navigation bar, but it should be put into the “higher level” – UITabbarController View

Let us into a code

According to the above implementation principle, we can see that our main focus is to build a suitable animation controller. To be more precise, the details we need to implement are in UIViewControllerAnimatedTransitioning, as I explained in detail before, here I put the relevant code directly for reference

- (void) animateTransition: (id< UIViewControllerContextTransitioning> transitionContext) {UIImageView = [[UIImageView * screentImgView alloc]initWithFrame:CGRectMake (0, 0, ScreenWidth, ScreenHeight)]; UIImage * screenImg = [self screenShot]; screentImgView.image =screenImg; / / fromView and toViewController from fromViewController, toView UIViewController fromViewController = [transitionContext * viewControllerForKey:UITransitionContextFromViewControllerKey] * fromView; / / UIView = [transitionContext viewForKey:UITransitionContextFromViewKey]; UIViewController * toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView * toView = [transitionContext viewForKey: UITransitionContextToView Key]; CGRect fromViewEndFrame [transitionContext = finalFrameForViewController:fromViewController]; fromViewEndFrame.origin.x = ScreenWidth; CGRect = fromViewStartFrame fromViewEndFrame; CGRect toViewEndFrame = [transitionContext finalFrameForViewController:toViewController]; CGRect toViewStartFrame = toViewEndFrame; UIView * containerView = [transitionContext containerView]; if (self.navigationOperation = = UINavigationControllerOperationPush) {[self.screenShotArray addObject:screenImg]; //toViewStartFrame.origin.x = ScreenWidth; [containerView addSubview:toView]; toView.frame = toViewStartFrame; UIView = alloc]initWithFrame:CGRectMake (ScreenWidth * nextVC [[UIView 0, ScreenWidth, ScreenHeight, //[ne)]; XtVC addSubview:[toView snapshotViewAfterScreenUpdates:YES]]; [self.navigationController.tabBarController.view insertSubview:screentImgView atIndex:0]; //[self.navigationController.tabBarController.view addSubview:nextVC]; nextVC.layer.shadowColor [UIColor = blackColor].CGColor; nextVC.layer.shadowOffset = CGSizeMake (-0.8, 0); nextVC.layer.shadowOpacity = 0.6; self.navigationController.view.transform = CGAffineTransformMakeTranslation (ScreenWidth, 0); [UIView animateWithDuration: [self transitionDuration:transitionContext] animations:^{//toView.frame = toViewEndFrame; self.navigationController.view.transform = CGAffineTransformMakeTranslation (0, 0) (-Sc; screentImgView.center = CGPointMake ReenWidth/2, ScreenHeight / //nextVC.center = 2); CGPointMake (ScreenWidth/2, ScreenHeight / 2);} completion:^ (BOOL finished) {[nextVC removeFromSuperview]; [screentImgView removeFromSuperview]; [transitionContext completeTransition:YES];}];} if (self.navigationOperation = = UINavigationControllerOperationPop) {fromViewStartFrame.origin.x = 0; [containerView / addSubview:toView]; if removeCount is greater than 0 indicates that Pop has more than one the controller of if (_removeCount > 0) {for (NSInteger I = 0; I < _removeCount I; if (+ +) {I _removeCount = - 1) {/ / when deleting to jump page screenshot, not deleted, and the screenshots as ToVC screenshots show LastVcImgView.image [self.screenShotArray = lastObject]; _removeCount = 0; break;} else {[self.screenShotArray}} {removeLastObject]}; else lastVcImgView.image = [self.screenShotArray lastVcImgView.image = lastObject];} [self.screenShotArray lastObject]; screentImgView.layer.shadowColor [UIColor = blackColor].CGColor; screentImgView.layer.shadowOffset = CGSizeMake (-0.8, 0); screentImgView.layer.shadowOpacity = 0.6; [self.navigationController.tabBarController.view addSubview:lastVcImgView] [self.navigationController.tabBarController.view addSubview:screentImgView]; ; / / fromView.frame = fromViewStartFrame; [UIView = CGPointMake animateWithDuration:[self transitionDuration:transitionContext] animations:^{screentImgView.center (ScreenWidth * 3 / 2, ScreenHeight / 2); lastVcImgView.center = CGPointMake (ScreenWidth/2, ScreenHeight/2); //fromView.frame = fromViewEndFrame;} completion:^ (BOOL finished) {//[self.navigationController setNavigationBarHidden:NO]; [lastVcImgView removeFromSuperview]; [screentImgView removeFromSuperview]; removeLastObject] [transitionContext completeTransition:YES]; self.screenShotArray;}];}} - (void) removeLastScreenShot {[self.screenShotArray removeLastObject];} - (UIImage * screenSho) T {/ / will be a screenshot of the view, the root window controller view (must be free from the status bar, the default ios7 controller contains the status bar) UIViewController *beyondVC = self.navigationController.view.window.rootViewController; / / CGSize background picture total size size = beyondVC.view.frame.size; / / open context, using the parameters after the cut out of the original (YES 0 high quality UIGraphicsBeginImageContextWithOptions (size), YES, 0); / / CGRect = CGRectMake to rect rectangular clipping (0, 0, ScreenWidth, ScreenHeight); / / Note: iOS7 renderInContext: drawViewHierarchyInRect:afterScreenUpdates: [beyondVC.view drawViewHierarchyInRect:rect afterScreenUpdates:NO] by substitution; / / from the context, remove the UIImage UIImage *snapshot = UIGraphicsGetImageF (romCurrentImageContext); / / remember, the end of the context (the current bitmap graphics context based on the removal of the top of the stack) (UIGraphicsEndImageContext); / / return interception good picture return snapshot;}

Note: removeLastScreenShot need to call in the use of gestures used to remove Pop, save animation controller in the screenshot, or when the interactive and non interactive animation interchangeably, there will be confusion. Update: call popToViewController: (UIViewController *) viewController animated: (BOOL) animated Pop multiple pages once, or call popToRootViewControllerAnimated to directly back to the controller, like the need to clear the corresponding number of shots, and the need to cooperate with operation and navigation. The new code has been submitted to GitHub, and the corresponding parts of the animation controller have been updated in the article. The specific code is based on GitHub.

Look at the effect

We modulate the animation duration for two seconds to observe the effect

[iOS] let's solve all the problems in the navigation bar once and for all
complete effect.Gif


This article started four months ago, due to personal reasons as well as the work of the middle drag and drag, and finally in the recent completion, logical confusion please forgive me.

navigation and animation controller download address
using the method of navigation and animation produced controller:
1 will be the four files into the project
2 will require animation KLTNavigationController navigation bar can be inherited

If my article is helpful to you, please praise or comment. Thank you!