最近作項目碰見一個問題:UIScrollView上有許多UIButton,要實現既能點擊UIButton,又能滑動UIScrollView,這個實現沒有問題,不須要作額外的touch管理,UIScrollView能識別是點擊的UIButton仍是滑動自己,可是有一個效果上的問題,就是點擊UIButton時間短的話,不會高亮,可是確實是觸發點擊了,這樣就形成了假象,給人一種UIButton沒有被點擊的感受。若是點擊時間長的話沒有問題,會高亮。this
這麼看來,致使這樣現象應該就是時間長短的問題,順着這個問題想下去,就追尋到UIScrollView的touch原理,當UIScrollView接收到一個touch時,它會在一段時間(好像是150ms)內監聽該touch是否移動了,假如移動了(應該有一個移動範圍),則取消將touch發送到其子視圖(例如UIButton),UIScrollView自身接受該touch,進行滑動。看來應該就是這段判斷時間惹的禍了(這裏其實我還想不明白爲何明明點擊了Button,也確實觸發了點擊,卻沒有高亮狀態,哪位大神知道的話請指教),那要解決問題是否是就應該把這段時間取消掉呢,不要這個判斷時間,那麼UIButton應該就會當即響應併產生高亮狀態吧。正好UIScrollView中有一個屬性叫delaysContentTouches,官方文檔對它的解釋是:If the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value is NO , the scroll view immediately calls touchesShouldBegin:withEvent:inContentView:. The default value is YES.意思就是設置爲NO就不會存在那個150ms的判斷時間了,直接執行後續操做。那麼我們設置爲NO來試試唄。結果確實如所想那樣,UIButton當即響應並高亮。事件
可是…..別高興太早,雖然這個問題解決了,可是新的麻煩又產生了,螳螂捕蟬黃雀在後!你會發現UIScrollView滑動不像之前那樣了,假如touch down的那點落在UIButton上而後再滑動手指,UIScrollView不會滑動,可是UIButton仍然觸發,固然,這樣的結果也是應該的,你想一想,設置delaysContentTouches爲NO後,只要手指點在UIButton上,UIScrollView就會當即斷定爲這是點擊UIButton,而不會再等待看手指是否移動來決定是否要滑動自己了。文檔
那麼如何解決這個問題呢?你會想,有沒有什麼方法能夠在touch到UIbutton上並滑動時不觸發UIButton而讓UIScrollView本身滑動呢,強大的iOS沒有讓你失望,UIScrollView中有一個方法:touchesShouldCancelInContentView:,來看它的解釋:The scroll view calls this method just after it starts sending tracking messages to the content view. If it receives NO from this method, it stops dragging and forwards the touch events to the content subview. The scroll view does not call this method if the value of the canCancelContentTouches property is NO.意思就是當UIScrollView將touch事件交給子view後,當手指發生滑動時,調用此方法,假如返回NO,則將touch事件交給子view,若是返回YES,則交給UIScrollView處理,產生滑動。(可是前提是UIScrollView的canCancelContentTouches屬性是YES纔會調用這個方法,只要不是UIControll的子類,這個屬性默認是YES。)因此只要重寫UIScrollView的這個方法並返回YES就能夠啦,到此問題就解決了。既能當即響應UIButton,也能自由滑動UIScrollView。it