2009-09-13 101 views
3

我有一個UIView子類(CustomView爲這個問題的目的)有自己的處理所有touches事件(開始,移動,結束,取消)。我也有一個UIButton,它是CustomView的兄弟姐妹重疊它。如何將第一個響應者從一個UIView「轉移」到另一個UIView?

例如,我的視圖層次結構看起來像這樣:

  • 的UIView(控制器的視圖)
    • CustomView與幀(0,0,300,300)
    • 的UIButton與幀(0 ,0,100,50)

我想CustomView捕捉觸摸事件一旦用戶拖出了UIButton。通過調試日誌記錄,看起來UIControlEventTouchDragExit事件是要攔截的事件(儘管直到觸摸距按鈕100個像素左右纔會觸發,但這對此問題並不重要)。理想情況下,當拖動退出事件被觸發時,按鈕將停止接收觸摸移動事件,CustomView將得到一個touchesBegan事件(即使我需要自己僞造一個),以及所有未來的觸摸事件(touchesMoved,等)將被髮送到CustomView。

我曾嘗試以下,並沒有任何效果:

-(void)btnTouchDragExit:(id)sender 
{ 
    UIButton * btn = sender; 
    [btn resignFirstResponder]; 
    [customView becomeFirstResponder]; 
} 

我認爲根本UITouch對象(這是跨越觸摸事件一致)沒有被重定目標在CustomView點。我怎樣才能達到預期的效果?

回答

5

只要使用hitTest:withEvent:找出「應該」接收事件的視圖,然後將事件轉發到適當的視圖。在進入按鈕之前,您可能需要做一些跳舞才能攔截事件,但這就是hitTest:withEvent:的原因。

+0

通過繼承UIButton並覆蓋touchesMoved,我已經能夠做到這一點(步行超級視圖樹調用hitTest,直到它找到一個觸摸點在它) ..但是,我必須手動將觸摸事件(從該點開始)轉換爲該視圖。是否沒有系統調用,以便Cocoa/UIWindow/UIApplication將觸摸發送到新視圖?在Win32中,它是ReleaseCapture/SetCapture(newWnd).. – Jason

+0

調用hitTest:withEvent:在超級視圖上,它會告訴你它的哪個子視圖是事件的第一響應者。一旦你弄明白了,只需調用'touches(開始|移動|結束):withEvent:' –

+1

這很有效,但這正是我試圖避免的,也就是因爲這需要子類化,並且通過這樣做我只能有這種行爲在自定義按鈕上(不是圓角矩形或任何其他)。在將觸摸事件轉發到諸如UIScrollViews和UIWebViews之類的東西時,我也看到了奇怪的事情,所以它可能不是一個完全通用的解決方案。 我會將問題留待一段時間,看看是否有任何其他建議。 – Jason

1

你必須覆蓋canBecomeFirstResponder返回YES否則becomeFirstResponder什麼都不做。這已經完成UIControl s,但不是UIView s

+1

添加到我的UIView子類沒有幫助。繼承UIButton並強制重定向觸摸事件仍然是需要的。從概念的角度來看,似乎爲了讓這個工作起作用,我不會調用'[customView becomeFirstResponder]',但應該調用像'[UIApplication assignFirstResponder:customView]'或其他靜態/全局功能。 – Jason