2014-09-19 67 views
4

我有一個點擊手勢識別器的視圖。該視圖的子視圖是我的自定義類的一個實例,它從UIControl繼承。我有一個問題,UIControl子類有時會允許觸摸事件通過父視圖時,它不應該。UIControl endTrackingWithTouch不叫

內UIControl子類,我已重寫這些函數(代碼是在斯威夫特)

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    return true 
} 

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    // The code here moves this UIControl so its center is at the touchpoint 
    return true 
} 

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent) 
{ 
    // Something important happens here! 
} 

這個系統如果用戶在UIControl內着陸時工作得很好,在 X周圍拖動控制和Y方向,然後升起屏幕。在這種情況下,所有這三個函數都被調用,並且發生了「重要的事情」。

但是,如果用戶用UIControl觸摸,在X方向上拖動控件只有,然後擡起屏幕,我們有問題。前兩個函數被調用,但是當觸點脫離屏幕時,會調用輕擊手勢識別器,並且不會調用endTrackingWithTouch。

我如何確保始終調用endTrackingWithTouch?

回答

3

我以一種我認爲是黑客的方式解決了這個問題,但根據UIGestureRecognizer的工作原理,沒有其他選擇。

發生了什麼事是,輕拍手勢識別器取消了控件的跟蹤並註冊輕擊手勢。這是因爲當我水平拖動時,我恰好拖着很短的距離,這被解釋爲輕擊手勢。

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    pointerToSuperview.pauseGestureRecognizer() 
    return true 
} 

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    // The code here moves this UIControl so its center is at the touchpoint 
    return true 
} 

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent) 
{ 
    // Something important happens here! 
    pointerToSuperview.resumeGestureRecognizer() 
} 

override func cancelTrackingWithEvent(event: UIEvent?) 
{ 
    pointerToSuperview.resumeGestureRecognizer() 
} 

在上海華盈的類:

點擊手勢識別器必須同時UIControl被跟蹤被禁用

pauseGestureRecognizer() 
{ 
    tapGestureRecognizer.enabled = false 
} 

resumeGestureRecognizer() 
{ 
    tapGestureRecognizer.enabled = true 
} 

這工作,因爲我不是在處理多點觸控(這是正常的我在跟蹤與UIControl的接觸時不會接收輕擊事件)。

理想情況下,控件不應該告訴視圖暫停手勢識別器 - 手勢識別器不應該插手控件的觸摸開始!但是,即使將手勢識別器的cancelsTouchesInView設置爲false,也無法防止此情況。

+0

很好的答案。有時您可以使用手勢的代表方法而不是禁用手勢: 可選的func gestureRecognizer(_ gestureRecognizer:UIGestureRecognizer, shouldReceiveTouch touch:UITouch) - > Bool – viggio24 2015-09-01 12:22:39

+0

如果您實現自己的TapGestureRecognizer並將其添加到控件中,任何超級觀點之前都會點擊。這樣您就不需要了解視圖層次結構中其他識別器的任何信息。以下詳情... – 2017-03-26 00:23:51

1

當UIControl在跟蹤觸摸時移動時,可能會取消其跟蹤。嘗試覆蓋cancelTrackingWithEvent並查看是否屬於這種情況。如果你看到取消,你將不得不跟蹤你在這個控制的父級層次結構中的一個不動的視圖。

+0

這結束了這個問題!奇怪的是,它只在水平拖動時觸發取消,但我只需要通過使UIView子視圖移動(而不是UIControl本身)的全屏UIControl來解決此問題。 – user1021430 2014-09-22 20:42:34

+0

其實我回來了。跟蹤事件沒有被取消,因爲我正在更改UIControl的框架。這是因爲每當我水平拖動時,我恰好在短距離拖着。這觸發了手勢識別器,因爲它被解釋爲點擊,並取消了跟蹤事件。 – user1021430 2014-09-23 23:04:05

1

我知道這是舊的,但我遇到了同樣的問題,檢查你的一個超級視圖是否具有手勢識別器,並在需要使用UIControl時關閉它們。

我實際上已經結束了將UIControl的超級視圖更改爲主窗口,以避免這種衝突(因爲它在彈出窗口中)。

2

有一種方法可以解決這個很好的自包含:實例化自己的TapGestureRecognizer並將其附加到您的自定義控件,例如,在Objective-C,

_tapTest = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; 
_tapTest.numberOfTapsRequired = 1; 
[self addGestureRecognizer:_tapTest]; 

,然後實現tapped操作處理程序來處理自來水:

- (void)tapped:(UITapGestureRecognizer *)recognizer {...} 

在我的情況,我處理tapped一樣endTrackingWithTouch:withEvent:;你的旅費可能會改變。

這樣,你得到任何上海華盈之前水龍頭可以搶奪它,你不必擔心你的控制背後的視圖層次。