UIPageViewController兼顧無(wú)彈簧效果和側(cè)滑返回


效果圖.gif

前言

閑來(lái)無(wú)事翻著公司的項(xiàng)目總覺(jué)得用UIPageViewControlle封裝的分頁(yè)控制器既不能側(cè)滑返回又有彈簧效果很不爽蛙吏,于是開(kāi)始折騰一下,期間遇到了一些坑,但終于柳暗花明。在此記錄一下填坑過(guò)程,分享給大家颅湘。

目標(biāo)

  1. 去掉UIPageViewController在Scroll樣式下的彈簧效果。
  2. 實(shí)現(xiàn)分頁(yè)控制器的側(cè)滑返回栗精。

開(kāi)始

網(wǎng)上搜索了下禁止彈簧效果的相關(guān)這個(gè)問(wèn)題闯参,發(fā)現(xiàn)了一段代碼:

__block UIScrollView *scrollView = nil;
[_pageViewController.view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([obj isKindOfClass:[UIScrollView class]])
    {
        scrollView = (UIScrollView *)obj;
    }
}];
if (scrollView ) scrollView.delegate = self;
        
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    scrollView.bounces = NO;
}

加上代碼果然可以,但是好景不長(zhǎng)悲立,當(dāng)我點(diǎn)擊分段控制器分頁(yè)后鹿寨,滾動(dòng)手勢(shì)居然失效了這顯然不是我想要的效果。并且直接改變UIScrollView的代理這種方法顯然不好薪夕,雖然delegate初始值為空脚草,但這種做法不安全,加上還要更改非公開(kāi)view的屬性原献,就更加的不安全了馏慨。然后我打印了UIPageViewController內(nèi)的一些信息:

(lldb) po _pageViewController.view.subviews
<__NSArrayM 0x608000245550>(
<_UIQueuingScrollView: 0x7fcaad02d400; frame = (0 0; 375 667); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x608000247050>; layer = <CALayer: 0x60800023fcc0>; contentOffset: {375, 0}; contentSize: {1125, 667}>
)

(lldb) po [_pageViewController.view.subviews[0] superclass]
UIScrollView

(lldb) po [_pageViewController.view.subviews[0] valueForKey:@"gestureRecognizers"]
<__NSArrayI 0x60000025b900>(
<UIScrollViewDelayedTouchesBeganGestureRecognizer: 0x6080001abb40; state = Possible; delaysTouchesBegan = YES; view = <_UIQueuingScrollView 0x7fcaad02d400>; target= <(action=delayed:, target=<_UIQueuingScrollView 0x7fcaad02d400>)>>,
<UIScrollViewPanGestureRecognizer: 0x7fcaac608b10; state = Possible; delaysTouchesEnded = NO; view = <_UIQueuingScrollView 0x7fcaad02d400>; target= <(action=handlePan:, target=<_UIQueuingScrollView 0x7fcaad02d400>)>; must-fail = {
        <UIScrollViewPagingSwipeGestureRecognizer: 0x6080003c2490; state = Possible; view = <_UIQueuingScrollView 0x7fcaad02d400>; target= <(action=_handleSwipe:, target=<_UIQueuingScrollView 0x7fcaad02d400>)>>
    }>,
<UIScrollViewPagingSwipeGestureRecognizer: 0x6080003c2490; state = Possible; view = <_UIQueuingScrollView 0x7fcaad02d400>; target= <(action=_handleSwipe:, target=<_UIQueuingScrollView 0x7fcaad02d400>)>; must-fail-for = {
        <UIScrollViewPanGestureRecognizer: 0x7fcaac608b10; state = Possible; delaysTouchesEnded = NO; view = <_UIQueuingScrollView 0x7fcaad02d400>; target= <(action=handlePan:, target=<_UIQueuingScrollView 0x7fcaad02d400>)>>
    }>
)

發(fā)現(xiàn)UIPageViewController的view下有一個(gè)叫UIQueuingScrollView的view,他的父類是UIScrollView,并且有三個(gè)手勢(shì)其中UIScrollViewPanGestureRecognizer手勢(shì)就是UIQueuingScrollView的父類UIScrollView公開(kāi)的panGestureRecognizer手勢(shì),大家可以打印地址查看姑隅。既然可以直接拿到控制UIPageViewController翻頁(yè)的手勢(shì)那問(wèn)題就清晰了写隶,只需要在適當(dāng)?shù)臅r(shí)候禁止掉這個(gè)手勢(shì)不就可以不讓用戶繼續(xù)滾動(dòng)了嗎。

解決問(wèn)題

1.關(guān)鍵方法

//UIGestureRecognizerDelegate 返回YES才響應(yīng)手勢(shì) 返回NO手勢(shì)失效
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer;

//UIGestureRecognizer 當(dāng)otherGestureRecognizer手勢(shì)失效時(shí)才相應(yīng)調(diào)用此方法的手勢(shì)
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;

2.手勢(shì)

  1. 側(cè)滑返回手勢(shì)
  2. UIPageViewController的滾動(dòng)手勢(shì)
  3. 為UIQueuingScrollView新添加一個(gè)pan手勢(shì)(fakePan)

3.關(guān)鍵代碼

 __block UIScrollView *scrollView = nil;
[_pageViewController.view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([obj isKindOfClass:[UIScrollView class]]) scrollView = (UIScrollView *)obj;
        
}];
if(scrollView)
{
//新添加的手勢(shì)讲仰,起手勢(shì)鎖的作用
    _fakePan = [UIPanGestureRecognizer new];
    _fakePan.delegate = self;
    [scrollView addGestureRecognizer:_fakePan];
    [scrollView.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.fd_fullscreenPopGestureRecognizer];
    [scrollView.panGestureRecognizer requireGestureRecognizerToFail:_fakePan];
    [_fakePan requireGestureRecognizerToFail:self.navigationController.fd_fullscreenPopGestureRecognizer];
}

//UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
    if (translation.x <= 0)
    {
        return (_currentIndex == _vcArray.count - 1 && transitionFinish);
    }
    else
    {
        return (_currentIndex ==0 && transitionFinish);
    }
}

4.說(shuō)明

側(cè)滑返回我是用的UINavigationController+FDFullscreenPopGesture分類慕趴,fd_fullscreenPopGestureRecognizer就是側(cè)滑返回的手勢(shì)。當(dāng)_fakePan和fd_fullscreenPopGestureRecognizer手勢(shì)不響時(shí)分頁(yè)視圖的滾動(dòng)手勢(shì)才響應(yīng)。在最后一頁(yè)左滑或第一頁(yè)右滑時(shí)_fakePan才響應(yīng)秩贰。fd_fullscreenPopGestureRecognizer的響應(yīng)條件是UINavigationController+FDFullscreenPopGesture內(nèi)部實(shí)現(xiàn)的我們這里只需要設(shè)置在顯示第一頁(yè)時(shí)才開(kāi)啟這個(gè)手勢(shì)即可霹俺。

總結(jié)

  1. 通過(guò)手勢(shì)之間的優(yōu)先級(jí)(個(gè)人覺(jué)得“手勢(shì)鎖”更形象)柔吼,實(shí)現(xiàn)了UIPageViewController的無(wú)彈簧效果和側(cè)滑返回毒费。
  2. 缺陷:快速滑動(dòng)或一直拖動(dòng)不放松時(shí)會(huì)出現(xiàn)彈簧效果,因?yàn)槭鞘謩?shì)實(shí)現(xiàn)的不可避免的會(huì)出現(xiàn)這樣的問(wèn)題愈魏,個(gè)人覺(jué)得不太影響效果觅玻。
  3. 如果不需要側(cè)滑返回只要?jiǎng)h除與側(cè)滑手勢(shì)有關(guān)的代碼。
  4. 在實(shí)現(xiàn)公開(kāi)API無(wú)法直接實(shí)現(xiàn)的效果是應(yīng)該盡量的不去改動(dòng)非公開(kāi)屬性培漏,而是在此基礎(chǔ)上增加實(shí)現(xiàn)溪厘。

Demo地址

Demo-GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市牌柄,隨后出現(xiàn)的幾起案子畸悬,更是在濱河造成了極大的恐慌,老刑警劉巖珊佣,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹋宦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咒锻,警方通過(guò)查閱死者的電腦和手機(jī)冷冗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惑艇,“玉大人蒿辙,你說(shuō)我怎么就攤上這事”醢停” “怎么了思灌?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)恭取。 經(jīng)常有香客問(wèn)我泰偿,道長(zhǎng),這世上最難降的妖魔是什么秽荤? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任甜奄,我火速辦了婚禮,結(jié)果婚禮上窃款,老公的妹妹穿的比我還像新娘课兄。我一直安慰自己,他們只是感情好晨继,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布烟阐。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜒茄。 梳的紋絲不亂的頭發(fā)上唉擂,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音檀葛,去河邊找鬼玩祟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屿聋,可吹牛的內(nèi)容都是我干的空扎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼润讥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼转锈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起楚殿,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤撮慨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后脆粥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體砌溺,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年冠绢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抚吠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弟胀,死狀恐怖楷力,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情孵户,我是刑警寧澤萧朝,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站夏哭,受9級(jí)特大地震影響检柬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜竖配,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一何址、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧进胯,春花似錦用爪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诸衔。三九已至,卻和暖如春颇玷,著一層夾襖步出監(jiān)牢的瞬間笨农,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工帖渠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谒亦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓阿弃,卻偏偏與公主長(zhǎng)得像诊霹,于是被迫代替她去往敵國(guó)和親羞延。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渣淳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件伴箩、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • 春與秋之間有夏相隔 秋的顏色是春的守望 問(wèn)春你是眷戀生機(jī)盎然的綠入愧? 還是愛(ài)著秋為你呈現(xiàn)的金黃? 春在我的耳邊輕聲細(xì)...
    獨(dú)白隨心閱讀 315評(píng)論 1 2
  • 說(shuō)明 本文是作者Lefe所創(chuàng)嗤谚,轉(zhuǎn)載請(qǐng)注明出處棺蛛,如果你在閱讀的時(shí)候發(fā)現(xiàn)問(wèn)題歡迎一起討論。本文會(huì)不斷更新巩步。 正文 由于...
    Lefe閱讀 571評(píng)論 0 0
  • 端午節(jié)放假三天 回家擼了三天娃 然后被三波人分別催著談戀愛(ài)椅野。 依次是我舅媽终畅、閨蜜、叔叔伯伯姑姑嬸嬸竟闪。 理由是到了2...
    噫呀_August閱讀 889評(píng)論 2 0