自定義導航欄返回按鈕點選事件
阿新 • • 發佈:2019-02-08
開發中經常會遇到 點選導航欄返回按鈕時不想 pop 回上一級控制器,而是回到 某一級控制器 或者需要在pop回去的時候回傳一些資料,但檢視文件發現,系統並沒有給我們直接提供這樣的方法。
那麼我們先來分析如何獲取返回按鈕的點選事件。
返回按鈕在導航欄上,所以我們先找到導航控制器UINavigationController的標頭檔案,他有一個屬性
@property(nonatomic,readonly) UINavigationBar *navigationBar;
我們知道返回按鈕就在 navigationBar上,在看一下 UINavigationBar 的標頭檔案,我們並沒有發現有返回按鈕的屬性或者返回按鈕的點選方法;
但是我們發現 navigationBar 有一個代理屬性
@property(nullable,nonatomic,weak) id delegate;
檢視 UINavigationBarDelegate 的方法中有一個方法是:
- (BOOL)navigationBar:(UINavigationBar )navigationBar shouldPopItem:(UINavigationItem
哈哈,從方法名上我們已經看出這個方法就是我們要找的了!
由於navigationBar 是NavigationController的屬性,我們推測 navigationBar 的 代理就是NavigationController, 於是我就在 NavigationController 裡重寫了上面那個代理方法,發現在點選返回按鈕的時候,確實呼叫了這個方法,^^ 有沒有覺得我們已經接近真相了 O(∩∩)O
等不及啦,直接上程式碼了
寫一個導航控制器的基類
#import <UIKit/UIKit.h>
@interface GZNavigationController : UINavigationController
@end
---------------------------
#import "GZNavigationController.h"
#import "GZViewController.h"
@interface GZNavigationController ()
@end
@implementation GZNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - UINavigationBarDelegate
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
{
if (self.viewControllers.count > 1) {
GZViewController *topVc = (GZViewController *)self.viewControllers.lastObject;
BOOL isPop = YES;
if ([topVc respondsToSelector:@selector(shouldPopItem)]) {
isPop = [topVc performSelector:@selector(shouldPopItem)];
if (isPop) {
dispatch_async(dispatch_get_main_queue(), ^{
[self popViewControllerAnimated:YES];
});
} else {
//shouldPopItem 方法返回no時發現返回按鈕的圖示,顏色變淡了,遍歷導航欄上的子空間,修改它的透明度為1
for(UIView *subview in [navigationBar subviews]) {
if(subview.alpha < 1.) {
[UIView animateWithDuration:.25 animations:^{
subview.alpha = 1.;
}];
}
}
}
return NO;
}
}
return YES;
}
@end
寫一個檢視控制器的基類
@interface GZViewController : UIViewController
/**
自定義導航欄返回按鈕的點選事件方法
@return 是否返回上一級控制器 ,return YES 返回上一級控制器,如果不想返回上一級控制器,可以重寫此方法,處理完自己的邏輯後 return NO;
*/
- (BOOL) shouldPopItem;
@end
--------------------------
#import "GZViewController.h"
@interface GZViewController ()
@end
@implementation GZViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (BOOL) shouldPopItem
{
//基類中預設 返回YES,也就是pop到上一級控制器
return YES;
}
@end
子類只需要重寫 - (BOOL) shouldPopItem 方法,就可以自定義返回按鈕的點選事件了。
如有問題,歡迎評論交流!