自定義iOS的Back按鈕(backBarButtonItem)和pop互動手勢(interactivepopgesturerecognizer)
序
說到自定義UINavigetionController的返回按鈕,iOS7以後,多了一個“<” 這樣的返回圖示,而目前主流的應用,都是隻保留了“<”,而去掉了文字,那麼怎麼樣自定義一個自己的“<"按鈕,或者用系統的“<”,但不要文字呢?
1.設定中的返回按鈕(帶文字)
2.音樂中播放時(不帶文字)
1、直接上答案
注:本文程式碼,如果沒有說明,都是從A導航檢視push到B導航檢視時,在A導航視圖裡設定的程式碼。//下面這兩句是讓系統的返回按鈕的文字為空,從而達到隱藏文字的作用 UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil]; self.navigationItem.backBarButtonItem = backItem; //這句就是push了,所以在push前加上這樣一句,就保留了系統的自帶的“<",並且文字為空 [self.navigationController pushViewController:registerVC animated:YES];
看圖:
2、帶著問題看答案:
1、上面的方法,只是利用了系統的自帶"<", 有人可能就問,那如果我想自定義圖示呢?
//下面兩行就是自定義,替換系統的“<"圖示 【1】 [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]]; [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]]; UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil]; self.navigationItem.backBarButtonItem = backItem;
這個方法,如果只是適配iOS 7以上,那麼,是目前比較好的解決方案了。
特點:
1.實現了自定義圖示,可以沒有文字,
2.儲存了iOS 7以上系統的pop手勢返回。
如果要適配iOS 6,那麼就要判斷系統版本,如果大於iOS 7,就用上面的程式碼,如果低於iOS 7.0,就用另外的程式碼(下面在介紹)
效果如下圖:
backItem;
2、那麼,我們在A檢視設定的程式碼,系統是如何實現從A檢視push到B檢視後,顯示在B檢視的?
看圖:
顯示原理【2】:
1、如果B檢視有一個自定義的左側按鈕(leftBarButtonItem),則會顯示這個自定義按鈕;
2、如果B沒有自定義按鈕,但是A檢視的backBarButtonItem屬性有自定義項,則顯示這個自定義項;
3、如果前2條都沒有,則預設顯示一個後退按鈕,後退按鈕的標題是A檢視的標題。
3、如果理解了第2點,那麼怎樣自定義程式碼,才能適配iOS 6和iOS 7以上呢?
自定義要求:
1.自定義圖示,文字可要可不要。
2.對於iOS 7以上,保留pop手勢.
分析:如果在A檢視自定義了返回按鈕,又要適配iOS6 ,但由於iOS6 下沒有手勢返回,所以只能點選左上角返回,怎麼處理?
直接上答案:
方案一【3】:
在A檢視中:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) //如果系統版本在iOS 7.0以上,執行
{
[self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"name="navibar_back_btn_bg_normal.png"]];
[self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backItem;
}
在B檢視中:
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) //如果系統版本在iOS 7.0以下(不包括7.0),執行
{
//導航條返回按鈕
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
[button setFrame:CGRectMake(0,0,30,30)">];
[button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButtonItem;
}
#pragma mark - 跳轉回去
- (void)jumpBack:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}
方案二:
//在A檢視中:
//開啟iOS7的滑動返回效果
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
[self.navigationController pushViewController:registerVC animated:YES];
//在B檢視中(ViewDidLoad):
//導航條返回按鈕
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
[button setFrame:CGRectMake(0,0,30,30)];
[button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButtonItem;
#pragma mark - 跳轉回去
- (void)jumpBack:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}
這個方案,不用適配iOS 6和iOS 7,與方案一區別是,箭頭比較靠右邊,為什麼?說到這個,我下一篇文章在會針對Navigation層次結構在說吧。 如圖:
方案三:
在B檢視中:- (void)viewWillAppear:(BOOL)animated
{
// 注意,這個<span style="font-family: Arial, Helvetica, sans-serif;">interactivePopGestureRecognizer</span><span style="font-family: Arial, Helvetica, sans-serif;">屬性是iOS 7才有的</span>
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
//導航條返回按鈕
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]
forState:UIControlStateNormal];
[button setFrame:CGRectMake(0,0,30,30)];
[button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = barButtonItem;
#pragma mark - 跳轉回去
- (void)jumpBack:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}
3、自定義幾點說明
1.返回文字可以自定義為照片
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed: @"navibar_back_btn_bg_normal.png"] style:(UIBarButtonItemStylePlain) target:nil action:nil];
self.navigationItem.backBarButtonItem = backItem;
看圖:
第二個"<",就是自定的圖片,這個自定義有意思嗎?大家看著用吧
2.自定義檢視無效!
UIView * view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 44)];
view.backgroundColor = [UIColor colorWithRed:0.263 green:1.000 blue:0.311 alpha:1.000];
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.backBarButtonItem = backItem;
3.自定義按鈕~
注意這個相對第1個自定義照片的區別:backBarButtonItem不能用View檢視方法自定義,而leftBarButtonItem可以哦!
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"] forState:UIControlStateNormal];
[button setFrame:CGRectMake(0, 0, 30, 44)];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.<span style="color:#ff0000;">leftBarButtonItem</span> = barButtonItem;
這個自定義,根據【2】,可以知道其作用,在這裡不在多說。
4.pop手勢
//官方文件:
NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : UIViewController
@property(nonatomic, assign) id<UINavigationControllerDelegate> delegate;
@property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0);
以上的方法,都是基於系統自帶的UINavigationController來自定義,如果不是系統的,比如淘寶的是自定義的UINavigation,所以沒有利用系統的pop手勢,而是自定義手勢。又比如天貓的只用到【2】的改變圖示,但文字都是統一的“返回”,並且部分頁面,不用pop手勢,直接彈回去。【分析於:2014.11.23日】
最後,大家都試試自定義自己的back按鈕吧!如果你有更多更好的自定義方法,記得分享哦!還有很多細節我沒有說到,如果大家感興趣的,可以自己在深入研究一下哦~
4、附錄:
【1】關於系統自帶的“<”圖示的官方解釋:
/*
The back indicator image is shown beside the back button.
The back indicator transition mask image is used as a mask for content during push and pop transitions
Note: These properties must both be set if you want to customize the back indicator image.
*/
@property(nonatomic,retain) UIImage *backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
@property(nonatomic,retain) UIImage *backIndicatorTransitionMaskImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
根據上面文件:
1、只有這兩個屬性都設定了,才會顯示自定義的圖片。
2、這兩個屬性,只能用於iOS 7以上。
3、很多人問為什麼要設定“backIndicatorTransitionMaskImage”這個屬性,看官方文件就知道,當push、pop時顯示的是這張image,但是疑問的是,當我設定這張照片跟“backIndicatorImage”屬性的照片不一樣時,系統不管是push,還是pop,還是完成時,都只會顯示"backIndicatorImage"屬性設定的照片。但由於文件沒有更多資訊,所以,這個問題我也就沒有找到答案。
【2】參考一大神的總結:
UINavigationController Class Reference去,在“Updating the Navigation Bar”小節,有這麼一段話:
The bar button item on the left side of the navigation bar allows for navigation back to the previous view controller on the navigation stack. The navigation controller updates the left side of the navigation bar as follows:
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the leftBarButtonItem property of the view controller’s navigation item.
- If the top-level view controller does not have a custom left bar button item, but the navigation item of the previous view controller has a valid item in itsbackBarButtonItem property, the navigation bar displays that item.
- If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the value of the title property of the previous view controller—that is, the view controller one level down on the stack. (If there is only one view controller on the navigation stack, no back button is displayed.)
我大致解釋一下,使用pushViewController切換到下一個檢視時,navigation controller按照以下3條順序更改導航欄的左側按鈕。
1、如果B檢視有一個自定義的左側按鈕(leftBarButtonItem),則會顯示這個自定義按鈕;
2、如果B沒有自定義按鈕,但是A檢視的backBarButtonItem屬性有自定義項,則顯示這個自定義項;
3、如果前2條都沒有,則預設顯示一個後退按鈕,後退按鈕的標題是A檢視的標題。
【3】關於判斷處理說明,和判斷系統版本程式碼
1.說明:如果系統在7.0以上,那麼由於有屬性【1】,所以非常容易在A檢視push前處理,但是iOS 6系統下,沒有這個屬性,又利用【2】原理,所以在B檢視下,自定義一個leftBarButtonItem按鈕,處理點選事件,這就是我目前所做到的,最好的方案。 2.系統版本判斷程式碼//檢查系統版本
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
官方文件:
+ (UIDevice *)currentDevice;
@property(nonatomic,readonly,retain) NSString *name; // e.g. "My iPhone"
@property(nonatomic,readonly,retain) NSString *model; // e.g. @"iPhone", @"iPod touch"
@property(nonatomic,readonly,retain) NSString *localizedModel; // localized version of model
@property(nonatomic,readonly,retain) NSString *systemName; // e.g. @"iOS"
@property(nonatomic,readonly,retain) NSString *systemVersion; // e.g. @"4.0"
@property(nonatomic,readonly) UIDeviceOrientation orientation; // return current device orientation. this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
@property(nonatomic,readonly,retain) NSUUID *identifierForVendor NS_AVAILABLE_IOS(6_0); // a UUID that may be used to uniquely identify the device, same across apps from a single vendor.
nice~相關推薦
自定義iOS的Back按鈕(backBarButtonItem)和pop互動手勢(interactivepopgesturerecognizer)
序 說到自定義UINavigetionController的返回按鈕,iOS7以後,多了一個“<” 這樣的返回圖示,而目前主流的應用,都是隻保留了“<”,而去掉了文字,那麼怎麼樣自定義一個自己的“<"按鈕,或者用系統的“<”,但不要文字呢? 1.設定
vue中自定義全域性按鈕修飾符和自定義全域性指令
最近比較懶 不想打字~我就直接上個圖吧 這是自定義全域性按鈕修飾符:其實那個f2只是繫結的時候需要的名字 跟形參實際意義差不多 關鍵是後面的鍵盤碼 比如我打個114(f3的鍵盤碼) 我繫結f2 實際上我要按f3才能觸發這次事件 這是全域性自定義指令 比如下面
android自定義相機(帶邊框和按鈕)
前兩個月專案要求不能呼叫系統的相機,那就只能用自定義的了,查了一些資料,自己再研究了一下,自定義的相機還是有點複雜的,佈局和程式碼中都要用到一個重要的SurfaceView。 一、建立佈局,佈局的背景框可以讓美工給出,這裡姑且就是一個藍色的邊框,然後下面有三個按鈕,我里布局檔案activit
Android項目實戰(十五):自定義不可滑動的ListView和GridView
con app lis androi color max XP xtend exp 原文:Android項目實戰(十五):自定義不可滑動的ListView和GridView不可滑動的ListView (RecyclweView類似) public class NoSc
HTML自定義選取按鈕(input樣式的按鈕)
自定義檔案上傳按鈕 谷歌瀏覽器下,預設的按鈕是這個樣子的: 火狐瀏覽器下是醬紫的: IE瀏覽器下是這個樣子的: 個人表示真的醜陋,無法接受! 修改 首先 <!DOCTYPE html> <html&g
iOS 底部按鈕 工具欄 Tabbar 及 Tabbar 的自定義(中間突出)
大多數應用使用系統自帶的Tabbar就能夠滿足需求 通常情況都是在AppDelegate.m裡建立一個UITabBarController將其它的控制器用UINavigationController包裝一層,再新增到UITabBarController的viewControllers裡。再將UI
2.3四種執行緒連線池的配置和使用(和自定義執行緒池)
四種執行緒連線池的配置和使用 最終呼叫類和方法 {引數有 核心執行緒數目,最大執行緒數目,存活時間(當前執行緒執行完這個任務之後,等待下一個任務到來的最長等待時間。如果在這個時間內沒有新的任務來到,那當前執行緒就會退出),時間單位,等待佇列(用於存放待執行的任務)} public
LayoutParams和onMeasure的效率(自定義16:9圖片)
-- SetLayoutParams和onMeasure的差別 setLayoutParams:設定view的寬度和高度。 onMeasure: 設定view的可見寬度和高度。 1) LayoutParams RelativeLayout.LayoutParams par
微信小程式之——自定義分享按鈕(完整版)
1.宣告 onShareAppMessage 函式 onShareAppMessage() { return { title: '彈出分享時顯示的分享標
遊戲製作之路(31)建立自定義的按鈕
在前面學習了怎麼樣建立按鈕,也學習了顯示純文字,不過這些都是使用預設的模式來顯示的,但是遊戲開發人員常常使用自定義的按鈕比較多,因為它顯示多樣化,同樣可以進行換圖美化,也可以符合使用者的個性定義化。因此,這次來學習使用GUIStyle元件來定義按鈕的樣式。 比如建立如下圖的按鈕: 這個
dedecms自定義獲取上級欄目名稱和連結的標籤 (返回上級欄目按鈕)
<?php if(!defined('DEDEINC')) exit('Request Error!'); function lib_type2(&$ctag,&$refObj) { global $dsql,$en
深入分析Spring屬性編輯器(預設屬性編輯器和自定義屬性編輯器)
在Spring配置檔案或配置類裡,我們往往通過字面值為Bean各種型別的屬性提供設定值:不管是double型別還是int型別,在配置檔案中都對應字串型別的字面值。BeanWrapper填充Bean屬性時如何將這個字面值轉換為對應的double或int等內部型別呢?我們可以隱約
如何使用VS建立SharePoint自定義Ribbon選單(圖文和程式碼)
如何使用VS建立SharePoint自定義Ribbon選單 SharePoint Ribbon選單 SharePoint 2010為我們帶來了很多新功能,這些新功能使得SharePoint更像是一個Office客戶端應用程式,這無疑是令人振奮的。提到Office就不能不
註解(Annotation)自定義註解(四)--編譯期註解解析講解和手寫ButterKnife
註解(Annotation)自定義註解(四)–編譯期註解解析講解和手寫ButterKnife 前言 前面兩篇講解了執行期註解的使用和xutils原始碼的解析,以及手動打造自己的IOC框架。但是執行期註解由於效能問題被一些人所詬病,所以這裡我們講下編譯器註
netty中自定義協議(加碼器和解碼器)
1、什麼是粘包/拆包 一般所謂的TCP粘包是在一次接收資料不能完全地體現一個完整的訊息資料。TCP通訊為何存在粘包呢?主要原因是TCP是以流的方式來處理資料,再加上網路上MTU的往往小於在應用處理的訊息資料,所以就會引發一次接收的資料無法滿足訊息的需要,導致粘包的存在。處理粘包的唯一方法就
Java異常----自定義異常類(throw和throws關鍵字的用法)
Java的異常處理的五個關鍵字, try、catch、finally、throw、throws 的關係: 處理異常方式: 1 try-catch 捕獲到異常後在catch中進行處理 2 throws
Java for Web學習筆記(三五):自定義tag(3)TLDS和Tag Handler
JSTL的TLD 這是JSTL採用的方式。TLD(Tag Library Descriptor)描述tag和function,以及具體執行的java程式碼tag handler。Tag Handler是javax.servlet.jsp.tagext.Tag或javax.servlet.jsp.tage
iOS 底部按鈕 工具欄 Tabbar 及 Tabbar 的自定義(中間突出)
大多數應用使用系統自帶的Tabbar就能夠滿足需求 通常情況都是在AppDelegate.m裡建立一個UITabBarController將其它的控制器用UINavigationController包裝一層,再新增到UITabBarController的viewContro
Android 自定義Dialog (有圓角和和已適配大螢幕的廣告機)
在開發過程中,有時需要自定義的Dialog,設計的需求是,按照螢幕的比例來顯示Dialog,需要有圓角。效果如下圖。 自定義程式碼Dialog 程式碼如下: CustomDialog.class public class CustomDialog
微信小程式(三)自定義分享按鈕和原生分享&區分不同按鈕的分享&帶引數分享和獲取
官方的分享 點選右上角的三個點 /** * 使用者點選右上角分享 */ onShareAppMessage: function(ops) { wx.showShareMenu({