iOS冷知識(shí):任意設(shè)置UIScrollView的滑動(dòng)觸摸區(qū)域。

前言

???前言: UIScrollViewUITableView是iOS中最常用的控件。而UITableView又是繼承自UIScrollView的,所以一個(gè)iOS程序員的工作可能會(huì)有很長(zhǎng)一段時(shí)間是在折騰一個(gè)或多個(gè)UIScrollView。了解UIScrollView的屬性和特點(diǎn)很有必要!
???在我們通常的認(rèn)知里,想要一個(gè)UIScrol lView隨著我們的手指滑動(dòng)而滑動(dòng),那么我們的手指必須在UIScrollView的范圍內(nèi)滑動(dòng)并且這個(gè)scrollview上層沒有任何別的view遮擋。但是其實(shí)我們是有辦法改變這個(gè)范圍的,使得即使我們?cè)?strong>UIScrollView以外的地方滑動(dòng)依舊可以使得UIScorllview產(chǎn)生滑動(dòng)。

實(shí)現(xiàn)

???如圖我們?cè)谝粋€(gè)viewcontroller的view上添加了一個(gè)scrollview,然后又addsubview一個(gè)白色的topview遮擋scrollview,那么當(dāng)我們嘗試滑動(dòng)scrollview的時(shí)候會(huì)發(fā)生以下情況:

未命名.gif

???原因是我們都知道了,根據(jù)iOS響應(yīng)鏈的規(guī)則通過(guò)hit-test找到找到點(diǎn)擊區(qū)域最上層的view,然后通過(guò)最上層的view找到firstResponder,讓firstResponder處理這個(gè)事件。
???響應(yīng)鏈條在本次滑動(dòng)事件的處理流程大致如下:當(dāng)我們嘗試在topview滑動(dòng)的時(shí)候,會(huì)使用hit-test來(lái)找出最上層的view響應(yīng)當(dāng)前滑動(dòng)事件。監(jiān)測(cè)到白色topview是最上層的view所以會(huì)把事件交給白色topview,但是topview并沒有不處理事件,所以需要向它nextResponder也就是它的superview,viewcontroller的view來(lái)處理,以此類推,發(fā)現(xiàn)并沒有view能夠處理這個(gè)事件,所以這個(gè)事件被作廢。我們的scrollview全程并未參與自然無(wú)法接受事件
???關(guān)于響應(yīng)鏈的詳細(xì)原理這里并不展開。

轉(zhuǎn)機(jī)

???點(diǎn)開UIScrollView.h,我們能看到UIScrollView有一個(gè)屬性panGestureRecognizer:

@property(nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer API_AVAILABLE(ios(5.0));

打印該屬性如下:

(lldb) po self.scrollView.panGestureRecognizer
<UIScrollViewPanGestureRecognizer: 0x7fb24a7080a0; state = Possible; delaysTouchesEnded = NO; view = <UIScrollView 0x7fb24c01b200>; target= <(action=handlePan:, target=<UIScrollView 0x7fb24c01b200>)>>

發(fā)現(xiàn)這個(gè)手勢(shì)是一個(gè)UIScrollViewPanGestureRecognizer,也就是處理UIScrollView滑動(dòng)的手勢(shì),它的view是
view = <UIScrollView 0x7fb24c01b200>;
也就是UIScrollView本身。這也就是為什么UIScrollView的滑動(dòng)一定要在UIScrollView范圍內(nèi)。
既然UIScrollView把處理滑動(dòng)的手勢(shì)暴露給我們了,那我們是不是可以把這個(gè)手勢(shì)添加到別的view上呢?
答案是:可以!
正如我們剛才說(shuō)的響應(yīng)鏈的原理,我們只要把UIScrollViewpanGestureRecognizer添加到topview和scrollview的共同父view,也就是這里的UIViewController的view上就可以實(shí)現(xiàn)點(diǎn)擊整個(gè)屏幕都能滑動(dòng)UIScrollView了!

    [self.view addGestureRecognizer:self.scrollView.panGestureRecognizer];

再看一下效果:


滑動(dòng).gif

更加驚喜的是,我們不僅可以修改UIScrollView的手勢(shì)觸發(fā)view為任意view,而且可以得到這個(gè)手勢(shì)的回調(diào):

[self.scrollView.panGestureRecognizer addTarget:self action:@selector(scrollViewPan:)];

- (void)scrollViewPan:(UIPanGestureRecognizer*)gesture
{
    if (gesture.state == UIGestureRecognizerStateBegan) {
    }else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == 
    }else if (UIGestureRecognizerStateChanged) {
    }
}

不用擔(dān)心這個(gè)回調(diào)會(huì)影響scrollview本身的滑動(dòng),他們并不會(huì)沖突。

拓展

由此拓展開來(lái),我們可以把 scrollview的panGerturerecognizer屬性添加到任意我們想要添加的view上,實(shí)現(xiàn)更加有趣的效果,比如:

修改滑動(dòng)區(qū)域.gif

結(jié)論:改變UIScrollView的滑動(dòng)手勢(shì)panGerturerecognizer的作用view,就可以改變UIScrollView的滑動(dòng)手勢(shì)響應(yīng)view,實(shí)現(xiàn)在任意view上響應(yīng)UIScrollView的滑動(dòng)手勢(shì)

最后附上demo

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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