iOS-返回手勢之無侵入性新增
首先, 起因就是被要求為一個已經開發並上線的專案新增返回手勢, 因為本身並不熟悉專案, 所有必須使用無侵入性的方法去實現, 實現的方案也是千千萬, 只是說明一下我所使用的方法, 自認為超級簡潔和方便。
1.runtime新增手勢給UIViewcontroller
最先想到的就是利用runtime新增手勢給UIViewcontroller, 而且系統自帶側滑手勢的回撥方法handleNavigationTransition:,我們在自己的手勢上直接用它的回撥方法, 大大減少了我們的程式碼量和複雜度。
#import "UIViewController+popGesture.h"
@implementation UIViewController (popGesture)
+ (void)load{
[super load];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 假如要開啟controller的統計 ,則把下面這行程式碼開啟
__gbh_tracer_swizzleMethod([self class], @selector(loadView), @selector(newLoadView));
});
}
- (void)newLoadView {
[self newLoadView];
id target = self.navigationController.interactivePopGestureRecognizer.delegate;
// handleNavigationTransition:為系統私有API,即系統自帶側滑手勢的回撥方法,我們在自己的手勢上直接用它的回撥方法
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
panGesture.delegate = self; // 設定手勢代理,攔截手勢觸發
[self.view addGestureRecognizer:panGesture];
// 一定要禁止系統自帶的滑動手勢
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
// 什麼時候呼叫,每次觸發手勢之前都會詢問下代理方法,是否觸發
// 作用:攔截手勢觸發
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 當前控制器是根控制器時,不可以側滑返回,所以不能使其觸發手勢
if(self.navigationController.childViewControllers.count == 1)
{
return NO;
}
return YES;
}
//// 允許多個手勢併發
//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
// return YES;
//}
// 交換方法
void __gbh_tracer_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
@end
這樣就實現了介面返回,是不是很簡單,不過這樣只能實現UIViewController介面的返回,在擁有UITableView和UIScrollview時就失效了,這是為什麼呢?
因為我們的返回程式碼是載入在UIViewController上,並沒有為UIScrollview新增,返回的手勢並不能傳遞到UIViewController,所以就失效了
2.處理滾動檢視手勢問題
為了無侵入依然使用分類的方法,依然我們已經分析到原因,只需要滾動檢視將我們需要的返回手勢傳遞下去即可
#import "UIScrollView+popGesture.h"
@implementation UIScrollView (popGesture)
#define IPHONE_H [UIScreen mainScreen].bounds.size.height //螢幕的高度
#define IPHONE_W [UIScreen mainScreen].bounds.size.width // 螢幕的寬度
// 手勢事件會一直往下傳遞,不論當前層次是否對該事件進行響應。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([self panBack:gestureRecognizer]) {
return YES;
}
return NO;
}
//location_X可自己定義,其代表的是滑動返回距左邊的有效長度
- (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {
//是滑動返回距左邊的有效長度 左1/8有效區域
int location_X = 0.125 * IPHONE_W;
if (gestureRecognizer == self.panGestureRecognizer) {
UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint point = [pan velocityInView:pan.view];
UIGestureRecognizerState state = gestureRecognizer.state;
if (UIGestureRecognizerStateBegan == state || UIGestureRecognizerStatePossible == state) {
CGPoint location = [gestureRecognizer locationInView:self];
if (point.x > 0 && location.x < location_X && self.contentOffset.x <= 0) {
return YES;
}
}
}
return NO;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([self panBack:gestureRecognizer]) {
return NO;
}
return YES;
}
這樣任何滾動檢視都實現了滑動返回,是不是很簡單,雖然不會寫作,但是都是乾貨,覺得有用就給我個贊吧,你的贊就是我的動力。
相關文章
- 實現全屏返回手勢
- 無侵入引入Flutter模組Flutter
- 無侵入式工具-SmartTool
- js無侵入埋點方案JS
- 解決右滑返回手勢和UIScrollView中的手勢衝突UIView
- Android開發之無侵入式修改TabLayout tabIndicator寬度AndroidTabLayoutIndicator
- iOS右滑返回手勢深度全解和最佳實施方案iOS
- iOS-對圖片操作---新增到自定義相簿iOS
- iOS- 詳解文字屬性AttributesiOS
- .NET無侵入式物件池解決方案物件
- DiagnosticSource DiagnosticListener 無侵入式分散式跟蹤分散式
- iOS-無限迴圈輪播圖iOS
- 原始碼剖析@ApiImplicitParam對@RequestParam的required屬性的侵入性原始碼APIUI
- 自定義導航欄返回按鈕導致返回手勢失效問題
- iOS 側滑返回手勢與Scrollview衝突的解決辦法iOSView
- StateShot - 無侵入的歷史狀態管理庫
- StateShot – 無侵入的歷史狀態管理庫
- html5之新增表單屬性HTML
- Dexposed:Android平臺免Root無侵入AOP框架Android框架
- iOS-此證書的簽發者無效iOS
- 原始碼剖析@ApiImplicitParam對@RequestParam的required屬性侵入性原始碼APIUI
- 華為雲代理有什麼優勢,折扣,返傭,服務!
- 侵入式和非侵入式的區別
- 【SpringBoot DB 系列】Jooq 之新增記錄使用姿勢Spring Boot
- # 走位setTimeout,回手掏Event LoopOOP
- rcp新增屬性
- 客官,.NETCore無程式碼侵入的模型驗證瞭解下NetCore模型
- Spring boot+Swagger配置無侵入式Restful介面(二)Spring BootSwaggerREST
- iOS-元件化iOS元件化
- css新增屬性,讓瀏覽器檢查無法選中元素CSS瀏覽器
- 你可以零侵入式實現小程式的全域性狀態管理嗎
- iOS-模組解耦iOS解耦
- iOS-自定義PickerViewiOSView
- iOS-入門HelloWorldiOS
- 非侵入式無許可權應用內懸浮窗的實現
- Seata 無侵入式分散式事務服務的實現基石-JDBC篇分散式JDBC
- 為textarea新增maxlength屬性
- 猴年2016科技業十大趨勢預覽:蘋果谷歌侵入汽車蘋果谷歌