欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

iOS導(dǎo)航欄控制的一些總結(jié)

 更新時(shí)間:2019年07月12日 11:38:32   作者:哈雷哈雷_Wong  
這篇文章主要給大家介紹了關(guān)于iOS導(dǎo)航欄控制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位iOS開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

許久不寫UI,對(duì)UI的很多東西都生疏了,最近使用導(dǎo)航欄的各種場景做一些總結(jié)。

1.導(dǎo)航欄的顯示與隱藏

導(dǎo)航欄的顯示與隱藏,分兩種情況:

1.從不顯示導(dǎo)航欄的頁面push到顯示導(dǎo)航欄的頁面。

2.從顯示導(dǎo)航欄的頁面Push到不顯示導(dǎo)航欄的頁面。

注意:

1.如果導(dǎo)航欄不顯示時(shí),系統(tǒng)的側(cè)滑返回功能無效。

2.雖然側(cè)滑返回功能無效,但是導(dǎo)航欄的 .interactivePopGestureRecognizer.delegate還是存在的。

針對(duì)以上兩種情況分別處理,整個(gè)Push過程都假設(shè)是從A頁面跳轉(zhuǎn)到B頁面

1.1 從不顯示導(dǎo)航欄的頁面Push到顯示導(dǎo)航欄的頁面。

關(guān)于導(dǎo)航欄的顯示,是否順滑,是通過如下兩個(gè)方法來控制。

// 不顯示動(dòng)畫,導(dǎo)航欄顯示就比較突兀
[self.navigationController setNavigationBarHidden:YES];

// 顯示動(dòng)畫,在側(cè)滑時(shí),導(dǎo)航欄顯示就比較順滑
[self.navigationController setNavigationBarHidden:YES animated:YES];

所以,做法是:

A頁面:

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

B頁面:

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

1.2 從顯示導(dǎo)航欄的頁面跳轉(zhuǎn)到不顯示導(dǎo)航欄的頁面

這種情況的做法如下:

A頁面:

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

B頁面:

// 在頁面將要出現(xiàn)時(shí),記錄原始側(cè)滑手勢代理對(duì)象,并將手勢代理設(shè)置為當(dāng)前頁面
- (void)viewWillAppear:(BOOL)animated
{
 [super viewWillAppear:animated];
 
 self.interactivePopDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
 self.navigationController.interactivePopGestureRecognizer.delegate = self;
 
 [self.navigationController setNavigationBarHidden:YES animated:YES];
}

// 在頁面消失時(shí),還原側(cè)滑手勢代理對(duì)象
- (void)viewDidDisappear:(BOOL)animated
{
 [super viewDidDisappear:animated];
 
 self.navigationController.interactivePopGestureRecognizer.delegate = self.interactivePopDelegate;
 self.interactivePopDelegate = nil;
}

// 實(shí)現(xiàn)手勢代理,為了防止影響其他手勢,可以判斷一下手勢類型
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
 if ([gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
 return YES;
 }
 ...... 其他手勢的處理
 
 
 return NO;
}

2.統(tǒng)一重寫導(dǎo)航欄返回按鈕

有時(shí)候,我們可能需要統(tǒng)一工程中的返回按鈕樣式,比如都是 箭頭+返回 或者都是 箭頭。

方案有兩種:

1.創(chuàng)建一個(gè)BaseViewController,然后統(tǒng)一設(shè)置navigationItem.leftBarButtonItem。

2.重寫導(dǎo)航控制器的Push方法,在push之前,設(shè)置navigationItem.backBarButtonItem

注意:

如果重寫了導(dǎo)航欄的leftBarButtonItem,那么側(cè)滑返回功能也就失效了,需要側(cè)滑返回功能需要自己處理。

第一種方案比較簡單就不做贅述了,第二種方案是這樣的:

自定義導(dǎo)航控制器,然后重寫如下方法:

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

如果不需要返回這兩個(gè)字,只需要這樣寫就好。

- (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.監(jiān)聽返回按鈕的點(diǎn)擊事件

在有些場景,我們需要監(jiān)聽返回按鈕的事件。比如,當(dāng)頁面用戶輸入了一些內(nèi)容后,用戶要點(diǎn)擊返回,想要回到上一個(gè)頁面時(shí),提醒用戶是否要緩存已經(jīng)輸入的內(nèi)容。

如果我們重寫了導(dǎo)航欄的返回按鈕,那么處理這種情況就很Easy,不做贅述了。

但是,如果我們沒有重寫過系統(tǒng)的返回按鈕,想要處理這種情況就比較麻煩,但是也是可以處理的。

處理步驟如下:

1.首先創(chuàng)建一個(gè)UIViewController的類別,頭文件(.h)的內(nèi)容如下:

@protocol BackItemProtocol <NSObject>

- (BOOL)navigationShouldPopWhenBackButtonClick;

@end

@interface UIViewController (BackItem)<BackItemProtocol>

@end

@interface UINavigationController (BackItem)

@end

包含一個(gè)協(xié)議、UIViewController的類別、UINavigationController的類別。

然后,實(shí)現(xiàn)文件(.m)如下:

#import "UIViewController+BackItem.h"

@implementation UIViewController (BackItem)

- (BOOL)navigationShouldPopWhenBackButtonClick
{
 return YES;
}

@end


@implementation UINavigationController (BackItem)

// 這個(gè)其實(shí)是導(dǎo)航欄的協(xié)議方法,在這里重寫了
- (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

默認(rèn)是,不需要處理返回按鈕的事件,直接使用系統(tǒng)的pop方法。

但是,如果我們需要在用戶點(diǎn)擊返回按鈕時(shí),彈窗提示,那就需要導(dǎo)入這個(gè)類別。

然后,重寫一個(gè)方法:

- (BOOL)navigationShouldPopWhenBackButtonClick
{
 BOOL isFlag = 輸入框不為空等等條件
 if (isFlag) {
 UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:@"是否保存修改" preferredStyle:UIAlertControllerStyleAlert];
 UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
 // 這里延時(shí)執(zhí)行是因?yàn)閁IAlertController阻塞UI,可能會(huì)導(dǎo)致動(dòng)畫的不流暢
 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) {
 // 這里延時(shí)執(zhí)行是因?yàn)閁IAlertController阻塞UI,可能會(huì)導(dǎo)致動(dòng)畫的不流暢
 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.導(dǎo)航控制器的頁面跳轉(zhuǎn)方式

安卓中的頁面跳轉(zhuǎn)有四種方式: standard、singleTop、singleTask、singleInstance。

例如singleTask,在做IM類App,跳轉(zhuǎn)到聊天室的場景,就非常有用,可以保證控制器棧中只有一個(gè)聊天室,避免返回時(shí)層級(jí)太深。

iOS端如果要仿這個(gè)效果的話,可以利用導(dǎo)航控制器的API:

- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated

首先,為UINavigationController 創(chuàng)建一個(gè)類別。

比如:

UINavigationController+HLPushAndPop.h
UINavigationController+HLPushAndPop.m

然后,新增幾個(gè)方法:

拿兩個(gè)方法來舉例

- (void)hl_pushSingleViewController:(UIViewController *)viewController
  animated:(BOOL)animated;

- (void)hl_pushSingleViewController:(UIViewController *)viewController
  parentClass:(Class)parentClass
  animated:(BOOL)animated;

再然后,實(shí)現(xiàn)方法:

實(shí)現(xiàn)步驟:

  1. 創(chuàng)建新的數(shù)組復(fù)制導(dǎo)航控制器原來的堆棧中的控制器。
  2. 在原始堆棧數(shù)組中判斷是否存在該類型的控制器,如果存在記錄其索引。
  3. 在復(fù)制的數(shù)組中將索引及上方所有控制器移除。
  4. 把將要push出來的控制器添加到復(fù)制的數(shù)組中。
  5. 將新的控制器數(shù)組設(shè)置為導(dǎo)航控制器的棧數(shù)組,根據(jù)參數(shù)判斷是否要顯示動(dòng)畫。

我這邊做了一些發(fā)散,因?yàn)橐恍╊惪赡軙?huì)有很多子類,那么想要保證父類以及子類的實(shí)例都只有一個(gè),所以將方法做了改進(jìn)。

- (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以及其子類的實(shí)例,則按照方法1處理
 if (![viewController isKindOfClass:parentClass]) {
 [self hl_pushSingleViewController:viewController animated:animated];
 return;
 }
 
 // 判斷 導(dǎo)航控制器堆棧中是否有parentClass以及其子類的實(shí)例
 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;
 }
 
 // 如果存在,則將該實(shí)例及上面的所有界面全部彈出棧,然后將要push的界面放到棧頂。
 for (NSInteger i = childViewControllers.count - 1; i >= index; i--) {
 [newChildVCs removeObjectAtIndex:i];
 }
 
 [newChildVCs addObject:viewController];
 viewController.hidesBottomBarWhenPushed = (newChildVCs.count > 1);
 [self setViewControllers:newChildVCs animated:animated];
}

當(dāng)然了,除了上面這些場景,還可以擴(kuò)展出一些其他的場景,比如我們期望將要push出來的控制器再某個(gè)棧中控制器的后面或者前面,這樣當(dāng)點(diǎn)擊返回或者側(cè)滑時(shí),就直接回到了指定頁面了。

或者我們知道將要返回的頁面的類型,直接pop回指定頁面。

擴(kuò)展出來的其他方法都在Demo中了,有興趣的可以看一下。

地址是:HLProject (本地下載

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • iOS計(jì)算上次日期距離現(xiàn)在多久的代碼

    iOS計(jì)算上次日期距離現(xiàn)在多久的代碼

    這篇文章主要為大家詳細(xì)介紹了iOS計(jì)算上次日期距離現(xiàn)在多久的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • iOS開發(fā)避免安全隱患的要點(diǎn)總結(jié)

    iOS開發(fā)避免安全隱患的要點(diǎn)總結(jié)

    在本篇文章里小編給各位整理了關(guān)于iOS開發(fā)如何避免安全隱患的知識(shí)點(diǎn)總結(jié),需要的朋友們學(xué)習(xí)下。
    2019-07-07
  • iOS如何獲取漢字(簡體中文)筆畫數(shù)詳解

    iOS如何獲取漢字(簡體中文)筆畫數(shù)詳解

    這篇文章主要給大家介紹了關(guān)于iOS如何獲取漢字(簡體中文)筆畫數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • iOS 13適配匯總(推薦)

    iOS 13適配匯總(推薦)

    這篇文章主要介紹了iOS 13適配匯總,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • iOS異步下載圖片實(shí)例代碼

    iOS異步下載圖片實(shí)例代碼

    這篇文章主要介紹了iOS異步下載圖片實(shí)例代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • iOS利用Block逆向傳值的方式詳解

    iOS利用Block逆向傳值的方式詳解

    大家應(yīng)該都有所了解在iOS開發(fā)中,常見的幾種逆向傳值方式,有代理(delegate)、通知(NSNotification),block等等,之前已經(jīng)給大家介紹了通過代理實(shí)現(xiàn)逆向傳值的方法,這篇文章來給大家介紹如何通過Block進(jìn)行逆向傳值,有需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。
    2016-12-12
  • iOS應(yīng)用內(nèi)實(shí)現(xiàn)跳轉(zhuǎn)到手機(jī)淘寶天貓的方法

    iOS應(yīng)用內(nèi)實(shí)現(xiàn)跳轉(zhuǎn)到手機(jī)淘寶天貓的方法

    這篇文章主要給大家介紹了關(guān)于iOS應(yīng)用內(nèi)如何實(shí)現(xiàn)跳轉(zhuǎn)到手機(jī)淘寶天貓的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • iOS NSNotificationCenter通知中心使用小結(jié)

    iOS NSNotificationCenter通知中心使用小結(jié)

    IOS中經(jīng)常會(huì)使用到NSNotification和delegate來進(jìn)行一些類之間的消息傳遞,這篇文章主要介紹了iOS NSNotificationCenter使用小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • iOS制作framework靜態(tài)庫圖文教程

    iOS制作framework靜態(tài)庫圖文教程

    這篇文章主要為大家詳細(xì)介紹了iOS制作framework靜態(tài)庫圖文教程,感興趣的小伙伴們可以參考一下
    2016-08-08
  • iOS調(diào)試Block引用對(duì)象無法被釋放的小技巧分享

    iOS調(diào)試Block引用對(duì)象無法被釋放的小技巧分享

    這篇文章主要給大家分享介紹了關(guān)于iOS調(diào)試Block引用對(duì)象無法被釋放的小技巧,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位iOS開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評(píng)論