知識點總結:04-iOS自定義導航控制器側滑返回的多種實現方法

我們都知道,iOS7導航控制器默認自帶了側滑功能,當用戶在界面的左邊滑動的時候,就會有側滑功能。但是如果我們從從導航控制器的返回按鈕,就發現系統所帶的側滑返回功能無法使用。因此為了解決此問題,有以下方法實現:

方法一:導航控制器全屏滑動返回效果
當用戶在界面左邊拖動,就會觸發滑動手勢方法,并且有滑動返回功能,說明系統手勢觸發了方法,即調用了target的action方法,也就是說action方法內已經實現側滑返回。 系統自帶的滑動手勢interactivePopGestureRecognizer

// self指向的導航控制器,在導航控制器的viewDidLoad方法打印
- (void)viewDidLoad { 
      [super viewDidLoad]; 
      NSLog(@"%@",self.interactivePopGestureRecognizer);
}

打印結果知:
1.系統自帶的手勢是UIScreenEdgePanGestureRecognizer類型對象,屏幕邊緣滑動手勢
2.系統自帶手勢target是_UINavigationInteractiveTransition類型的對象
3.target調用的action方法名叫handleNavigationTransition:

全屏滑動代碼塊實現

- (void)viewDidLoad {
       [super viewDidLoad]; 

      // 獲取系統自帶滑動手勢的target對象 
      id target = self.interactivePopGestureRecognizer.delegate; 

      // 創建全屏滑動手勢,調用系統自帶滑動手勢的target的action方法 
      UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)]; 

      // 設置手勢代理,攔截手勢觸發 pan.delegate = self;

     // 給導航控制器的view添加全屏滑動手勢
     [self.view addGestureRecognizer:pan];

       // 禁止使用系統自帶的滑動手勢      
      self.interactivePopGestureRecognizer.enabled = NO;
}
      // 什么時候調用:每次觸發手勢之前都會詢問下代理,是否觸發。
      // 作用:攔截手勢觸發
      - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
       // 注意:只有非根控制器才有滑動返回功能,根控制器沒有。 
      // 判斷導航控制器是否只有一個子控制器,如果只有一個子控制器,肯定是根控制器 
      if (self.childViewControllers.count == 1) { 
      // 表示用戶在根控制器界面,就不需要觸發滑動手勢,
         return NO; } 
      return YES;
}

導航控制器全屏滑動注意點:
- 1.禁止系統自帶滑動手勢使用。
- 2.只有導航控制器的非根控制器才需要觸發手勢,使用手勢代理,控制手勢觸發。

  完成、這樣就搞定了, 親測此方法會與界面有滑動手勢的產生沖突,因此有第二種方法!

以上方法參考原文鏈接如下:
http://www.cocoachina.com/ios/20150811/12897.html?utm_source=tuicool)

方法二:實現自定義導航控制器邊緣滑動返回
方法二的實現原理和方法一一樣,只不過它還是使用的系統的邊緣手勢實現側滑返回功能。只需要在每個類里面添加如下代碼塊:
寫在.m中, 別忘了遵守 UIGestureRecognizerDelegate協議。

//當前導航控制器@property (nonatomic, strong) UIViewController *currentShowVC;
-(void)viewWillAppear:(BOOL)animated {
//設置代理
self.navigationController.interactivePopGestureRecognizer.delegate =(id)self;

//啟用系統自帶的滑動手勢 
self.navigationController.interactivePopGestureRecognizer.enabled = YES;

//判斷導航控制器是否只有一個子控制器,如果只有一個子控制器,肯定是根控制器,這里我的項目是有tabbar,所以在頁面切換之間設置是否顯示tababr。 
    if (self.navigationController.viewControllers.count == 1){ 
  //將當前導航控制器置空
         self.currentShowVC = Nil;
         [SharedAppDelegate setTabBarHidden:NO animated:YES];   
    }else{ 如果不是根控制器,就設置當前導航控制器為其本身。     
         self.currentShowVC = self; 
          [SharedAppDelegate setTabBarHidden:YES animated:NO]; 
}
}

手勢的代理方法

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ 
      if (gestureRecognizer ==     
          self.navigationController.interactivePopGestureRecognizer) { //當前導航控制器是根視圖控制器
           //the most important 
          return (self.currentShowVC ==         
          self.navigationController.topViewController); 
// 不要隱藏tabbar 
        [SharedAppDelegate setTabBarHidden:NO animated:NO]; 
}
    return YES;
}

方法三:(推薦使用)

  • 自定義UINavigationController
#import "ZGKNavigationViewController.h"

@interface ZGKNavigationViewController ()<UIGestureRecognizerDelegate>

@end

@implementation ZGKNavigationViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // self.interactivePopGestureRecognizer.delegate = nil;就是什么時候都可以滑動手勢,會有bug,無法點擊settingBtn
    // 設置手勢代理
    self.interactivePopGestureRecognizer.delegate = self;
    
    //    self.interactivePopGestureRecognizer.enabled = YES;
    
    // 設置導航控制器navigationBar和tabBar的背景顏色可以解決導航欄黑色點的bug
    [self.navigationBar setBackgroundImage:[UIImage imageNamed:@"navigationbarBackgroundWhite"] forBarMetrics:UIBarMetricsDefault];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


/**
 *  重寫push方法的目的 : 攔截所有push進來的子控制器(包括代碼和storyBoard實現的)
 *
 *  @param viewController 剛剛push進來的子控制器
 */
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (self.childViewControllers.count > 0) { // 如果viewController不是最早push進來的子控制器,則不用設置返回按鈕
        // 左上角
        UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [backButton setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal];
        [backButton setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted];
        [backButton setTitle:@"返回" forState:UIControlStateNormal];
        [backButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [backButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
        [backButton sizeToFit];
        // 這句代碼放在sizeToFit后面
        backButton.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
        [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
        viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
        // 隱藏底部的工具條
        viewController.hidesBottomBarWhenPushed = YES;
    }
    
    // 所有設置搞定后, 再push控制器(不要忘記調用父類方法)
    [super pushViewController:viewController animated:animated];

}

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

//- (UIViewController *)popViewControllerAnimated:(BOOL)animated
//{
//    return [super popViewControllerAnimated:NO];
//}
//
//- (NSArray<UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
//{
//    return [super popToViewController:viewController animated:NO];
//}
//
//- (NSArray<UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated
//{
//    return [super popToRootViewControllerAnimated:NO];
//}

#pragma mark - <UIGestureRecognizerDelegate>
/**
 *  手勢識別器對象會調用這個代理方法來決定手勢是否有效
 *
 *  @return YES : 手勢有效, NO : 手勢無效
 */
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
//    if (self.childViewControllers.count == 1) {
//        return NO;
//    }
//    
//    return YES;
    
    // 手勢何時有效 : 當導航控制器的子控制器個數 > 1就有效
    return self.childViewControllers.count > 1;
}

@end
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容