實(shí)現(xiàn)全屏滑動(dòng),解決UIScrollerView的沖突

實(shí)現(xiàn)全屏滑動(dòng),解決UIScrollerView的沖突

之前我們追求 讓你三行代碼, 今天我們追求讓你隨便寫(xiě)代碼,

喜歡單手操作的我在這里我要隆重地贊美一下,今日頭條,簡(jiǎn)書(shū)APP ,我喜歡他們的原因就是他們完美實(shí)現(xiàn)了全屏滑動(dòng),不像有些APP 還要點(diǎn)左上角或者屏幕邊緣才能返回,這不符合單身20多年的我的習(xí)慣!

裝逼結(jié)束,下面是正文:

今天我們要實(shí)現(xiàn)的是不需要寫(xiě)一行代碼,實(shí)現(xiàn)全屏滑動(dòng),并且解決UIScrollerView的沖突
先看下效果


演示2.gif

最后一個(gè)界面就是不要全屏滑動(dòng)的界面

創(chuàng)建一個(gè) UINavigationController的分類,在分類中操作
基礎(chǔ)知識(shí)
打印

NSLog(@"---------%@",self.navigationController.interactivePopGestureRecognizer);

得到的結(jié)果如下

<UIScreenEdgePanGestureRecognizer: 0x7f9ee0c3b5a0; 
state = Possible; 
delaysTouchesBegan = YES;
view = <UILayoutContainerView 0x7f9ee0c38170>; 
target= <(action=handleNavigationTransition:
target=<_UINavigationInteractiveTransition 0x7f9ee0c3b460>)>>

系統(tǒng)管理全屏滑動(dòng)的類是 UIScreenEdgePanGestureRecognizer 這個(gè)類
執(zhí)行者是 _UINavigationInteractiveTransition == self.interactivePopGestureRecognizer.delegate
方法是 handleNavigationTransition

知道上面的思路我們需要做的就是 用我們自己的手勢(shì)去攔截系統(tǒng)的手勢(shì),然后去實(shí)現(xiàn)系統(tǒng)全屏滑動(dòng)的效果 方法: <handleNavigationTransition>

首先我們自定義手勢(shì) popPanGestureRecognizer
他的taget 和action 還是系統(tǒng)的方法,但是 手勢(shì)的delegate 換成 self 就是導(dǎo)航欄控制器
然后通過(guò) runtime hook 在viewWillAppear 的方法中 將自己創(chuàng)建的手勢(shì)添加到 self.view 就是導(dǎo)航欄控制器

接下來(lái)需要處理手勢(shì)
首先需要設(shè)置

///是否允許接收手指的觸摸點(diǎn)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return self.childViewControllers.count > 1; // 只有非跟控制器才需要觸發(fā)手勢(shì)
}

在跟控制器中不響應(yīng)

同時(shí)還需要寫(xiě)下面的方法,處理手勢(shì)沖突

/// 只有當(dāng)系統(tǒng)側(cè)滑手勢(shì)失敗了,才去觸發(fā)ScrollView的滑動(dòng) 這個(gè)方法返回YES,第一個(gè)和第二個(gè)互斥時(shí),第二個(gè)會(huì)失效
/**
 第一個(gè)手勢(shì)是  <UIPanGestureRecognizer: 0x7fdd5d70ac90; state = Possible; view = <UILayoutContainerView 0x7fdd5d50ff20>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fdd5d40fd60>)>>
 第二個(gè)手勢(shì)是  <UIScrollViewPanGestureRecognizer: 0x7fdd5d425840; state = Possible; delaysTouchesEnded = NO; view = <UIScrollView 0x7fdd5d8ec000>; target= <(action=handlePan:, target=<UIScrollView 0x7fdd5d8ec000>)>>
 */
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

處理完手勢(shì)沖突后 需要處理 手勢(shì)的作用范圍,代碼如下:

///開(kāi)始進(jìn)行手勢(shì)識(shí)別時(shí)調(diào)用的方法是否接收一個(gè)手勢(shì)觸摸事件默認(rèn)為YES返回NO為不接收用處:可以在控件指定的位置使用手勢(shì)識(shí)別
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
    if ([[self valueForKey:@"_isTransitioning"] boolValue])
    {
        return NO;
    }
    if ([self.navigationController.transitionCoordinator isAnimated])
    {
        return NO;
    }
    if (self.childViewControllers.count <= 1)
    {
        return NO;
    }
    BOOL res = NO;
    if (self.isEnabled == YES)
    {
        // 側(cè)滑手勢(shì)觸發(fā)位置
        CGPoint location = [gestureRecognizer locationInView:self.view];
        CGPoint offSet = [gestureRecognizer translationInView:gestureRecognizer.view];
        BOOL ret = (0 < offSet.x && location.x <= self.recognizerLength);
        return ret;
    }
    return res;
}

如果你需要定制 在viewdidload方法中寫(xiě)下面的屬性

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
   這個(gè)屬性控制著 左邊滑動(dòng)手勢(shì)的區(qū)域      
        self.navigationController.recognizerLength = 100;
    });

除此之外
還可以設(shè)計(jì)成某一個(gè)界面不想要全屏滑動(dòng)的設(shè)計(jì)
給viewcontroller 添加一個(gè)分類 同時(shí)綁定一個(gè)屬性控制可用與否
具體代碼如下:
分別在 viewWillAppear 和 viewWillDisappear 對(duì)方法進(jìn)行交換 和賦值

-(void)_vcViewWillAppear:(BOOL)animated
{
    [self _vcViewWillAppear:animated];
    if (self.noPopAction)
    {
        self.navigationController.popPanGestureRecognizer.enabled = NO;
    }
}

-(void)_vcViewWillDisAppear:(BOOL)animated
{
    [self _vcViewWillDisAppear:animated];
    if (self.noPopAction)
    {
        self.navigationController.popPanGestureRecognizer.enabled = YES;
    }
}

實(shí)際使用的過(guò)程中中在 適當(dāng)位置寫(xiě)上下面的代碼就ok

 self.noPopAction = YES;  // 這個(gè)界面不想要全屏手勢(shì)了

到此不需要寫(xiě)一行代碼就可以搞定全屏滑動(dòng),并且也不影響你自己的 UISCrollerView的手勢(shì)

同學(xué)們?nèi)绻惺裁唇ㄗh反饋請(qǐng) 簡(jiǎn)書(shū)上聯(lián)系我

http://www.itdecent.cn/u/874b526fa570

同學(xué)們也別忘了支持一下我寫(xiě)的多張照片照片選擇框架

https://github.com/wangjinshan/IJSPhotoSDK

本篇文檔的內(nèi)容將放到

https://github.com/wangjinshan/IJSPhotoSDK 目錄下 IJSNavigationBack 文件夾下 需要的小伙伴 直接下載這個(gè)文件 然后放到自己的項(xiàng)目中可以了,不需要寫(xiě)代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,023評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,270評(píng)論 4 61
  • 導(dǎo)航控制器的返回按鈕設(shè)置以及一些細(xì)節(jié)處理 導(dǎo)航控制器的返回按鈕可以通過(guò)下面兩個(gè)屬性來(lái)設(shè)置 根據(jù)誰(shuí)的東西誰(shuí)管理的原則...
    追風(fēng)箏的boy閱讀 1,404評(píng)論 11 14
  • 玻璃窗外,微風(fēng)徐徐,今日陰天,好似我現(xiàn)在的心情。分手后的第三天,一切很平靜,平靜地好像我們從未遇見(jiàn),平靜地好像...
    雜草瑩閱讀 368評(píng)論 2 2
  • 孟女四月游人間, 粉帶桃紅遮嬌顏。 看盡花落芬芳匿, 散落凡塵護(hù)花難。
    軍玲閱讀 184評(píng)論 0 0

友情鏈接更多精彩內(nèi)容