Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of iOS Navigation Bar Control

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Editor to share with you the example analysis of iOS navigation bar control, I believe that most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!

1. Display and concealment of navigation bar

There are two situations in which the navigation bar is displayed or hidden:

1. Never the page that displays the navigation bar push to the page that displays the navigation bar.

two。 From pages that display the navigation bar Push to pages that do not display the navigation bar.

Note:

1. If the navigation bar is not displayed, the sideslip return function of the system is invalid.

two。 Although the sideslip return function is invalid, the .interactivePopGestureRecognizer.delegate of the navigation bar still exists.

In view of the above two situations, the whole Push process is assumed to be a jump from page A to page B.

1.1The page that displays the navigation bar is never Push to the page that displays the navigation bar.

Whether the display of the navigation bar is smooth or not is controlled by the following two methods.

/ / if the animation is not displayed, the display of the navigation bar is more abrupt [self.navigationController setNavigationBarHidden:YES]; / / the display of the navigation bar is more smooth when the animation is side-slipped [self.navigationController setNavigationBarHidden:YES animated:YES]

Therefore, the practice is:

A page:

-(void) viewWillAppear: (BOOL) animated {[super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:YES animated:YES];}

Page B:

-(void) viewWillAppear: (BOOL) animated {[super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:NO animated:YES];}

1.2 Jump from the page that displays the navigation bar to the page that does not display the navigation bar

The practice of this situation is as follows:

A page:

-(void) viewWillAppear: (BOOL) animated {[super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:NO animated:YES];}

Page B:

/ / record the original sideslip gesture proxy object when the page is about to appear, and set the gesture proxy to the current page-(void) viewWillAppear: (BOOL) animated {[super viewWillAppear:animated]; self.interactivePopDelegate = self.navigationController.interactivePopGestureRecognizer.delegate; self.navigationController.interactivePopGestureRecognizer.delegate = self; [self.navigationController setNavigationBarHidden:YES animated:YES] } / / when the page disappears, restore the side-slip gesture proxy object-(void) viewDidDisappear: (BOOL) animated {[super viewDidDisappear:animated]; self.navigationController.interactivePopGestureRecognizer.delegate = self.interactivePopDelegate; self.interactivePopDelegate = nil;} / / implement the gesture proxy. To avoid affecting other gestures, you can determine the gesture type-(BOOL) gestureRecognizerShouldBegin: (UIGestureRecognizer *) gestureRecognizer {if ([gestureRecognizer isKindOfClass: [UIScreenEdgePanGestureRecognizer class]]) {return YES;}. Processing of other gestures return NO;}

two。 Unified rewrite navigation bar return button

Sometimes, we may need to unify the style of the return button in the project, such as arrow + return or both arrows.

There are two options:

1. Create a BaseViewController, and then set the navigationItem.leftBarButtonItem uniformly.

two。 Override the Push method of the navigation controller and set the navigationItem.backBarButtonItem before push.

Note:

If the leftBarButtonItem of the navigation bar is rewritten, the sideslip return function is disabled, and the sideslip return function needs to be handled on its own.

The first scheme is relatively simple, so I don't want to repeat it. The second one is as follows:

Customize the navigation controller, and then override the following method:

-(void) pushViewController: (UIViewController *) viewController animated: (BOOL) animated {UIBarButtonItem * backItem = [[UIBarButtonItem alloc] initWithTitle:@ "returns" style:UIBarButtonItemStyleDone target:nil action:nil]; viewController.navigationItem.backBarButtonItem = backItem; [super pushViewController:viewController animated:animated];}

If you don't need to return these two words, just write it this way.

-(void) pushViewController: (UIViewController *) viewController animated: (BOOL) animated {UIBarButtonItem * backItem = [[UIBarButtonItem alloc] initWithTitle:nil style:UIBarButtonItemStyleDone target:nil action:nil]; viewController.navigationItem.backBarButtonItem = backItem; [super pushViewController:viewController animated:animated];}

3. Monitor the click event of the return button

In some scenarios, we need to listen for the events of the return button. For example, when the user of the page enters something, the user clicks back, and when he wants to go back to the previous page, remind the user whether to cache what he has already entered.

If we rewrite the return button of the navigation bar, it would be very Easy to deal with this situation, so I won't repeat it.

However, if we haven't overridden the system's return button, it's troublesome to deal with this situation, but it's manageable.

The processing steps are as follows:

1. First create a category of UIViewController, and the header file (.h) is as follows:

@ protocol BackItemProtocol-(BOOL) navigationShouldPopWhenBackButtonClick;@end@interface UIViewController (BackItem) @ end@interface UINavigationController (BackItem) @ end

Contains a protocol, the category of UIViewController, and the category of UINavigationController.

Then, the implementation file (.m) is as follows:

# import "UIViewController+BackItem.h" @ implementation UIViewController (BackItem)-(BOOL) navigationShouldPopWhenBackButtonClick {return YES;} @ end@implementation UINavigationController (BackItem) / / this is actually the protocol method of the navigation bar, which rewrites-(BOOL) navigationBar: (UINavigationBar *) navigationBar shouldPopItem: (UINavigationItem *) item {if ([self.viewControllers count]]

< [navigationBar.items count]) { return YES; } BOOL shouldPop = YES; UIViewController *vc = [self topViewController]; if([vc respondsToSelector:@selector(navigationShouldPopWhenBackButtonClick)]) { shouldPop = [vc navigationShouldPopWhenBackButtonClick]; } if (shouldPop) { dispatch_async(dispatch_get_main_queue(), ^{ [self popViewControllerAnimated:YES]; }); } else { for(UIView *subview in [navigationBar subviews]) { if(subview.alpha < 1) { [UIView animateWithDuration:.25 animations:^{ subview.alpha = 1; }]; } } } return NO;}@end 默认是,不需要处理返回按钮的事件,直接使用系统的pop方法。 但是,如果我们需要在用户点击返回按钮时,弹窗提示,那就需要导入这个类别。 然后,重写一个方法: - (BOOL)navigationShouldPopWhenBackButtonClick{ BOOL isFlag = 输入框不为空等等条件 if (isFlag) { UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:@"是否保存修改" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { // 这里延时执行是因为UIAlertController阻塞UI,可能会导致动画的不流畅 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.navigationController popViewControllerAnimated:YES]; }); }]; UIAlertAction *saveAction = [UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 这里延时执行是因为UIAlertController阻塞UI,可能会导致动画的不流畅 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self rightClick]; }); }]; [alertVC addAction:cancelAction]; [alertVC addAction:saveAction]; [self presentViewController:alertVC animated:YES completion:nil]; return NO; } return YES;} 4.导航控制器的页面跳转方式 安卓中的页面跳转有四种方式: standard、singleTop、singleTask、singleInstance。 例如singleTask,在做IM类App,跳转到聊天室的场景,就非常有用,可以保证控制器栈中只有一个聊天室,避免返回时层级太深。 iOS端如果要仿这个效果的话,可以利用导航控制器的API: - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated 首先,为UINavigationController 创建一个类别。 比如: UINavigationController+HLPushAndPop.hUINavigationController+HLPushAndPop.m 然后,新增几个方法: 拿两个方法来举例 - (void)hl_pushSingleViewController:(UIViewController *)viewController animated:(BOOL)animated;- (void)hl_pushSingleViewController:(UIViewController *)viewController parentClass:(Class)parentClass animated:(BOOL)animated; 再然后,实现方法: 实现步骤: 创建新的数组复制导航控制器原来的堆栈中的控制器。在原始堆栈数组中判断是否存在该类型的控制器,如果存在记录其索引。在复制的数组中将索引及上方所有控制器移除。把将要push出来的控制器添加到复制的数组中。将新的控制器数组设置为导航控制器的栈数组,根据参数判断是否要显示动画。 我这边做了一些发散,因为一些类可能会有很多子类,那么想要保证父类以及子类的实例都只有一个,所以将方法做了改进。 - (void)hl_pushSingleViewController:(UIViewController *)viewController animated:(BOOL)animated{ [self hl_pushSingleViewController:viewController parentClass:viewController.class animated:animated];}- (void)hl_pushSingleViewController:(UIViewController *)viewController parentClass:(Class)parentClass animated:(BOOL)animated{ if (!viewController) { return; } // 如果要push的界面不是 parentClass以及其子类的实例,则按照方法1处理 if (![viewController isKindOfClass:parentClass]) { [self hl_pushSingleViewController:viewController animated:animated]; return; } // 判断 导航控制器堆栈中是否有parentClass以及其子类的实例 NSArray *childViewControllers = self.childViewControllers; NSMutableArray *newChildVCs = [[NSMutableArray alloc] initWithArray:childViewControllers]; BOOL isExit = NO; NSInteger index = 0; for (int i = 0; i < childViewControllers.count; i++) { UIViewController *vc = childViewControllers[i]; if ([vc isKindOfClass:parentClass]) { isExit = YES; index = i; break; } } // 如果不存在,则直接push if (!isExit) { [self pushViewController:viewController animated:animated]; return; } // 如果存在,则将该实例及上面的所有界面全部弹出栈,然后将要push的界面放到栈顶。 for (NSInteger i = childViewControllers.count - 1; i >

= index; iMurt -) {[newChildVCs removeObjectAtIndex:i];} [newChildVCs addObject:viewController]; viewController.hidesBottomBarWhenPushed = (newChildVCs.count > 1); [self setViewControllers:newChildVCs animated:animated];}

Of course, in addition to the above scenarios, we can also expand some other scenarios, such as we expect the controller that will be push to be behind or in front of the controller in some stack, so that when we click back or side-slide, we will go directly to the specified page.

Or we know the type of page to be returned and pop directly back to the specified page.

The above is all the contents of the article "sample Analysis of iOS Navigation Bar Control". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report