簡介:對(duì)于在使用的UINavigation, 蘋果原生自帶屏幕邊緣右滑功能,性能非常好,但太過于雞肋.
本文主要分析蘋果右滑的實(shí)現(xiàn),以及實(shí)現(xiàn)全屏右滑.
* 首先看下蘋果的邊緣右滑
小結(jié):
1.0 系統(tǒng)實(shí)現(xiàn)屏幕右滑,因?yàn)槠溆幸皇謩?shì)
UIGestureRecognizer *interactivePopGestureRecognizer;
2.0 只能邊緣右滑,是應(yīng)為其手勢(shì)是邊緣觸發(fā)型手勢(shì);
打印該手勢(shì):
NSLog(@"%@", self.interactivePopGestureRecognizer);
輸出:
<UIScreenEdgePanGestureRecognizer: 0x7fae4ad5d6f0; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7fae4ad5bbf0>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f9858e96120>)>>
解析:蘋果怎么實(shí)現(xiàn)右滑?
- 手勢(shì)類型:
UIScreenEdgePanGestureRecognizer
(邊緣時(shí)才會(huì)觸發(fā)手勢(shì)) - 觸發(fā)手勢(shì)時(shí),對(duì)象(target):
_UINavigationInteractiveTransition
- 對(duì)象會(huì)調(diào)用的方法:
handleNavigationTransition:
- 此時(shí),就能實(shí)現(xiàn)邊緣右滑;
*當(dāng)我們重寫按鈕覆蓋系統(tǒng)按鈕時(shí):
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"返回" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
此時(shí)無論如何都不會(huì)有邊緣右滑功能.
*提出假設(shè):
1.0 是不是我們覆蓋navigation導(dǎo)航條按鈕后,其手勢(shì)被系統(tǒng)自動(dòng)釋放了呢?
此時(shí)再打印該手勢(shì):
NSLog(@"%@", self.interactivePopGestureRecognizer);
輸出:和上面打印結(jié)果一樣,說明手勢(shì)沒有被釋放.
2.0 既然手勢(shì)沒有被釋放,那么系統(tǒng)是不是做了什么事?
這時(shí)候我們有發(fā)現(xiàn)一個(gè)現(xiàn)象:
* 該手勢(shì)是添加給整個(gè)導(dǎo)航控制器的
* 在根控制器下,該手勢(shì)無效
* 只有在非根控制器下,手勢(shì)才有效
系統(tǒng)必定監(jiān)聽了手勢(shì)在什么控制器下才能正常工作,猜測(cè)一下是不是代理(代理不就是整天框個(gè)大眼睛觀察對(duì)象嘛!)
// 嘗試下,是否能夠打印該手勢(shì)的代理
NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
// 輸出結(jié)果如下;
<_UINavigationInteractiveTransition: 0x7f9858e96120>
// 在不覆蓋系統(tǒng)按鈕的情況下,此時(shí)嘗試
self.interactivePopGestureRecognizer.delegate = nil;
測(cè)試結(jié)果如下:
發(fā)現(xiàn)再在根控制器下觸發(fā)該手勢(shì)后,然后點(diǎn)擊跳到下一界面時(shí),程序假死.....ing;
結(jié)論:系統(tǒng)手勢(shì)有代理,且代理實(shí)現(xiàn)在根控制器下手勢(shì)無效(畢竟已經(jīng)是根控制器了,還想往右滑???)
3.0 是不是現(xiàn)在已經(jīng)在懷疑:當(dāng)覆蓋系統(tǒng)按鈕時(shí),代理對(duì)我們做了什么...
測(cè)試: 覆蓋按鈕,且把代理清空
// navigation viewDidload方法中
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.interactivePopGestureRecognizer.delegate = nil;
發(fā)現(xiàn)已經(jīng)可以實(shí)現(xiàn)屏幕邊緣右滑了,但是在根控制器下觸發(fā)左滑,由于設(shè)置代理為nil,會(huì)出現(xiàn)上述假死.
但我們可以這么解決
1.0 在根控制器下,把代理再設(shè)置回原來 (不常用)
2.0 自己設(shè)置代理,實(shí)現(xiàn)監(jiān)聽
// 實(shí)現(xiàn)方法2
// 1.手動(dòng)設(shè)置代理
self.interactivePopGestureRecognizer.delegate = self;
// 2.監(jiān)聽方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (self.childViewControllers.count == 1) {
// 根控制器下,不允許接受手勢(shì)
return NO;
}
return YES;
}
到此已經(jīng)解決:自定義按鈕下,實(shí)現(xiàn)屏幕邊緣右滑功能.
*怎么實(shí)現(xiàn)全屏右滑?
-
既然蘋果已經(jīng)提供好右滑功能,為什么我們不在蘋果的基礎(chǔ)上再進(jìn)一步呢?
- 分析:蘋果手勢(shì)是邊緣(edge)型觸發(fā),那么我們實(shí)現(xiàn)全屏手勢(shì)即可
代碼實(shí)現(xiàn):
// 全屏右滑,自己添加手勢(shì),采用系統(tǒng)的代理,以及調(diào)用系統(tǒng)的方法;李代桃僵
// 1.0 創(chuàng)建手勢(shì)
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
// 2.0 設(shè)置代理,處理根控制器下的業(yè)務(wù)
pan.delegate = self;
// 3.0 添加手勢(shì)到導(dǎo)航控制器的view
[self.view addGestureRecognizer:pan];
// 4.0 清空原生手勢(shì),以此避免不必要bug
self.interactivePopGestureRecognizer.enabled = NO;
// 實(shí)現(xiàn)代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// 根控制器下,手勢(shì)無效
return self.childViewControllers.count >1;
}
// 解析:
有沒有發(fā)現(xiàn)前面打印手勢(shì)時(shí):
target=<_UINavigationInteractiveTransition 0x7f9858e96120>)>>
打印手勢(shì)代理時(shí):
輸出:<_UINavigationInteractiveTransition: 0x7f9858e96120>
這兩貨是同一個(gè)對(duì)象....
那么在我們自定義手勢(shì)中,讓蘋果提供的對(duì)象,調(diào)用它提供的方法就好了:
initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)
全屏右滑效果圖:
由于截圖工具太爛,以及手速不行,截的圖都好丑....