iOS導航欄自定義返回按鈕以及設置導航欄透明交互

前言
相信大家對iOS的導航欄都會有自己的一點不爽,在項目開發過程中總是會出現這樣那樣莫名其妙的問題,而且對系統API提供的一些接口并不能達到很好的效果,一個小小的返回按鈕就把我們整的要命。網上對于返回按鈕的處理基本包括兩種:
1.使用self.navigationItem.leftBarButtonItem自定義自己的返回按鈕
2.通過[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:@"xx"]],[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage::[UIImage imageNamed:@"xx"]];來修改返回圖片
上面的兩種方式我就不具體說明他們會存在什么樣的問題了,我相信試過的人都應該會遇到過。

使用系統默認的返回按鈕
原本我以為使用下面的方法應該可以達到效果

+ (void)initialize{
    UINavigationBar * appearance = [UINavigationBar appearance];
    [appearance setBackIndicatorImage:[UIImage imageNamed:@"icon_common_back"]];
    [appearance setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"icon_common_back"]];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (![viewController.navigationItem.backBarButtonItem.title isEqualToString:@""]) {
        viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
                                                           initWithTitle:@""
                                                           style:UIBarButtonItemStylePlain
                                                           target:nil
                                                           action:nil];
    }
}```

但是出現的結果是這樣的
![0decedb8-86e5-4112-b473-93e7cb36fdf5.png](http://upload-images.jianshu.io/upload_images/5388324-6b852c52676e60f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

既然寬度不對,那么我就獲取對應的圖層重新設置它的寬度,但是試了之后雖然這個視圖可以達到效果,但是titleView 或者title的位置并沒有因為返回按鈕實際占位的減少而顯示正常(大家可以試試) ,可能有些人會說那么就獲取titleView這些圖層修改之,但是其實很復雜,我放棄了這種方法。

隨后我試了一下去掉圖片
  • (void)initialize{
    UINavigationBar * appearance = [UINavigationBar appearance];
    [appearance setBackIndicatorImage:[[UIImage alloc] init]];
    [appearance setBackIndicatorTransitionMaskImage:[[UIImage alloc] init]];
    }```
    效果是這樣的并且同樣將文字去掉,發現這個時候


    2784aa3a-ddcf-4ad5-8e8c-8f74559bdc74.png

那么問題就簡單了,那我就自己放一個imageView上去就把所有問題解決了。最后的效果是這樣的,具體的實現邏輯看我這里的代碼吧
https://github.com/BulletWu/BTNavigationBar

ffb26180-25dc-476c-9e45-bce5c1bf2be5.png

返回事件攔截
網上很多返回按鈕事件攔截的帖子,但是大多都是僅限于點擊返回按鈕的事件攔截,代碼也大同小異和下面一樣,當然我也是這樣去實現的。

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item{
    if([self.viewControllers count] < [navigationBar.items count]) {
        return YES;
    }
    UIViewController *topVC = self.topViewController;
    BOOL shouldPop = YES;
    if([topVC respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
        shouldPop = [topVC navigationShouldPopOnBackButton];
    }
    if (topVC.hidesBackButton) {
        shouldPop = NO;
    }
    if (shouldPop) {
        id<UIViewControllerTransitionCoordinator> coor = topVC.transitionCoordinator;
        if (coor && coor.initiallyInteractive) {
            return YES;
        }
        NSInteger itemCount = self.navigationBar.items.count;
        NSInteger n = self.viewControllers.count >= itemCount ? 2 : 1;
        UIViewController *popToVC = self.viewControllers[self.viewControllers.count - n];
        [self popToViewController:popToVC animated:YES];
        return YES;
    }else{
        for(UIView *subview in [navigationBar subviews]) {
            if(0. < subview.alpha && subview.alpha < 1.) {
                [UIView animateWithDuration:.25 animations:^{
                    subview.alpha = 1.;
                }];
            }
        }
        return NO;
    }
}

但是該方法無法攔截側滑返回的手勢,但是既然有點擊返回按鈕的手勢攔截,當然必須應該有側滑返回的手勢,但是系統側滑手勢設置的delegate對象為_UINavigationInteractiveTransition,是一個私有API,我們沒辦法覆寫它。但是手勢對象是interactivePopGestureRecognizer,是一個UIGestureRecognizer,而且可以想象系統一定是執行了這樣一句代碼self. interactivePopGestureRecognizer.delegate = _UINavigationInteractiveTransition實例對象,
那么我們的突破口就是重寫UIGestureRecognizer的setDelegate方法,但是我不想在UINavigationController中將interactivePopGestureRecognizer.delegate設置為self,因為我不能確定我能很好的控制這個delegate事件,事實證明,如果自己去設置也的確會出現這樣那樣的問題,那么我就使用消息轉發機制來實現,不多說了,還是看代碼吧

- (void)bt_navSetDelegate:(id<UIGestureRecognizerDelegate>)delegate{
  if ([NSStringFromClass([delegate class]) isEqualToString:@"_UINavigationInteractiveTransition"]) {
      if (delegate == nil) {
          delegate = self;
      }
      [self bt_navSetDelegate:self];
      self.gestureRecognizerDelegate = delegate != self ? delegate :nil;
  }else{
      [self bt_navSetDelegate:delegate];
  }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{    
  UIViewController *topViewController = [[self class] getCurrentVC];
  BOOL shouldPop = YES;
  if([topViewController respondsToSelector:@selector(navigationShouldPopOnPopGestureRecognizer)]) {
      shouldPop = [topViewController navigationShouldPopOnPopGestureRecognizer];
  }
  return shouldPop && [self.gestureRecognizerDelegate gestureRecognizerShouldBegin:gestureRecognizer];
}```

對于返回事件的一些事件我目前只做了

@protocol BTBackHandlerProtocol <NSObject>
@optional

  • (BOOL)navigationShouldPopOnBackButton; //是否允許觸發返回按鈕
  • (BOOL)navigationShouldPopOnPopGestureRecognizer; //側滑返回
  • (void)navigationDidPop;//pop成功 ,因為側滑返回可能取消
  • (void)navigationPopCancel;//側滑返回取消
    @end
我想有這些應該足夠了

**導航欄透明交互**
主要思想就是不隱藏導航欄,只修改透明度,具體看代碼吧
https://github.com/BulletWu/BTNavigationBar

**交流進步**
因為這個我自己也是剛寫的,希望大家來幫助我發現問題,然后解決問題,做一個完美的導航欄
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容