天天看點

UIScrollView的事件響應原理

UIScrollView的事件響應原理:

   (1)當多個視圖進行疊加的時候,touch事件一般是作用到最上面的視圖上;但是如果父視圖是UIScrollView,并且touch子視圖可能會造成父視圖UIScrollView的滾動時 

           那麼在手指觸摸到UIScrollView的視圖範圍之内的一瞬間,會産生下面的動作:

           * 攔截觸摸事件

           * 将 UIScrollView的 tracking屬性變為YES

           * 一個内置的計時器開始生效,用來監控在極短的時間間隔内 手指 是否發生了移動

          > * case1:當檢測到時間間隔内手指發生了移動,UIScrollView自己觸發滾動,取消發送tracking 給子視圖。tracking屬性變為NO。手指觸摸下即使有(可以響應觸摸事件的)内部控件也不會再響應觸摸事件。

          > * case2:當檢測到時間間隔内手指沒有移動,UIScrollView會發送tracking events到子視圖上。tracking屬性保持YES。手指觸摸下如果有(可以響應觸摸事件的)内部控件,則将觸摸事件傳遞給相應控件進行處理。

  (2)UIScrollView的子控件要想接收touch事件,即使用者點選UIScrollView上的子視圖時,先處理子視圖上的touch,而使 UIScrollView 不發生滾動。這時候就需要自定義UIScrollView,然後重載touchesShouldBegin:withEvent:inContentView:方法 ,進而決定該 UIScrollView 子視圖 是否接受 touch事件。 

  (3)自定義UIscrollView的幾個注意點

          (a). touchesShouldBegin:withEvent:inContentView 決定自己是否接收 touch 事件,YES:(自己不接收,發送事件)即不滾動;NO:(自己接收,不發送)即滾動;(PS:預設是YES)

          (b). touchesShouldCancelInContentView 開始發送 tracking messages 消息給 subview 的時候調用這個方法,決定是否發送 tracking messages 消息到subview。假如傳回 NO,發送。YES 則不發送(PS:1和2配合使用)

          (c). scorllView的屬性:delaysContentTouches 是個布爾值:                     當 delaysContentTouches =  YES 時,使用者觸碰開始後,scroll view要延遲一會,看看是否使用者有意圖滾動。如果使用者有滾動的意圖,那麼捕捉 touch-down 事件,否則就不捕捉。                     當 delaysContentTouches = NO 時,使用者觸碰開始後,scroll view 會立即觸發。 

核心代碼:

//view是使用者點選的視圖

- (

BOOL

)touchesShouldBegin:(

NSSet

*)touches withEvent:(UIEvent *)event inContentView:(UIView *)view

{

// 擷取一個UITouch

UITouch *touch = [touches anyObject];

// 擷取目前的位置

CGPoint current = [touch locationInView:

self

];

CGFloat x = [UIScreen mainScreen].bounds.size.width;

if

(current.x >= x + 10) {

//在子控件上,UIScrollView不接收觸碰事件,發送事件

return

YES

;

else

{

return

[

super

touchesShouldBegin:touches withEvent:event inContentView:view];

}

}

- (

BOOL

)touchesShouldCancelInContentView:(UIView *)view

{

if

([view isKindOfClass:

NSClassFromString

(@

"TapDetectingView"

)]) {

return

NO

;

else

{

return

[

super

touchesShouldCancelInContentView:view];

}

}

注意的問題

1. 如果storyboard中使用的是系統自帶的MKMapView,則不需要自定義scrollView

2. 判斷使用者目前點選的視圖時,點選BMKMapView對應的View類型是TapDetectingView,是以需要轉換一下