問題:
如果在UIScrollView的上面放置了一個按鈕,那么這個按鈕點擊的時候,按鈕的高亮狀態的圖片是不能顯示的。
原因:
這個由于UIScrollView和UIButton兩者的事件響應的沖突引起的。
解決方案:
這時候需要在UIScrollView的身上動手了,自定義一個CustomScrollView,重寫里面的touchesShouldCancelInContentView方法,然后用自定義的這個CustomScrollView,實例化后,設置其delaysContentTouches的值為false,這樣就解決了。
代碼:
class CustomScrollView:UIScrollView{
override func touchesShouldCancelInContentView(view: UIView) -> Bool {
return true
}
}
let scrollVeiw = CustomScrollView()
scrollVeiw.delaysContentTouches = false
原因進一步分析:
- 1:因為scrollView有一個150ms的延時判斷,當我們的手指放在scrollView上時,如果在這150ms內我們的手指有移動,那么這是事件就會判斷為“拖動scrollView的事件”,就不會被傳遞給它的子控件了;如果在這150ms內手指沒有移動,則將這個touch事件傳遞給其最適合響應的子控件。那么顯然將這個延時判斷去除問題就顯然解決了(self.scrollVeiw.delaysContentTouches = false)。
- 2:但是又會產生新的問題,就是當我們手指落在Button上時開始滑動scrollView,這時scrollView就不會滑動了。解決方案就是重寫scrollView的touchesShouldCancelInContentView方法,返回false。當UIScrollView將touch事件交給子view后,當手指發生滑動時,調用此方法,假如返回false,則將touch事件交給子view,如果返回false,則交給UIScrollView處理,產生滑動。
UIScrollView的工作原理:
UIScrollView的工作原理,當手指touch的時候,UIScrollView會攔截Event,會等待一段時間,在這段時間內,如果沒有手指沒有移動,當時間結束時,UIScrollView會發送tracking events到子視圖上。在時間結束前,手指發生了移動,那么UIScrollView就會進行移動,從而取消發送tracking。
用戶touch —> tracking真 —> 如果點擊一個可交互視圖上,判斷邏輯過程如下:
步驟1:根據delaysContentTouches的值,判斷什么時候步驟2(立刻還是判斷一定條件);
步驟2:調用touchesShouldBegin方法,如果返回值為yes,touch事件傳給子視圖;如果為no,touch事件不傳給子視圖,進入狀態n。(跳轉)
步驟3:touch move的,
3.1 如果canCancelContentTouches為no,不調用touchesShouldCancelInContentView方法,類也不scroll,進入狀態m;
3.2 如果canCancelContentTouches為yes,調 用touchesShouldCancelInContentView,根據touchesShouldCancelInContentView方法的返回值;如果是yes,進入狀態s。如果是no,進入狀態m。
狀態n :tracking為真,如果touch move的就scroll,touch松開,進入狀態e
狀態s :touch move中,類scroll,如果touch松開,進入狀態e
狀態m:touch move中,類不scroll,如果touch松開,進入狀態e
狀態e : 結束