2011-06-26 51 views
0

我有一個UITableView,我出現在UIPopoverController。表視圖顯示了可以拖放到主視圖上的元素列表。自定義UIGestureRecognizer不按預期方式工作

當用戶開始主要垂直的平移手勢時,我想讓UITableView照常滾動。當它一開始並不是垂直的時候,我希望應用程序將其解釋爲一個拖放操作。

我不幸在這條路上漫長的旅程迫使我創建一個自定義UIGestureRecognizer。在試圖得到基本正確的,我離開了這個習俗gesturer作爲第一個空的實現,一個只調用每五個自定義方法蘋果稱的超級版本應該重寫:

(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; 
(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; 
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; 
(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; 
(void)reset; 

此結果在沒有任何事情發生的情況下,即從未調用自定義手勢的動作方法,並且表視圖像往常一樣滾動。

對於我的下一個實驗,我在touchesBegan方法中將手勢狀態設置爲UIGestureRecognizerStateBegan

這導致手勢的動作方法觸發,使手勢看起來像標準UIPanGestureRecognizer一樣行爲。這顯然表明我負責管理手勢的狀態。

接下來,我在touchesMoved方法中將手勢狀態設置爲UIGestureRecognizerStateChanged。一切都還好。

現在,我嘗試在touchesMoved方法中將手勢的狀態設置爲UIGestureRecognizerStateFailed。我期待這個結束手勢並將事件流恢復到表視圖,但事實並非如此。它所做的只是停止觸發手勢的操作方法。

最後,我在touchesBegan方法中將手勢狀態設置爲UIGestureRecognizerStateFailed,之後我立即將其設置爲UIGestureRecognizerStateBegan

這會導致手勢只觸發其操作方法一次,然後將所有後續事件傳遞給表視圖。

所以......對於這麼長的問題抱歉......但是爲什麼如果我在touchesBegan方法中導致手勢失敗(在首次將狀態設置爲UIGestureRecognizerStateBegan之後),它是否將事件重定向到表視圖,如預期。但是如果我在touchesMoved(我可以檢測到移動主要是垂直的唯一位置)嘗試相同的技術,那麼爲什麼不會發生這種重定向?

回答

1

對不起,這比它實際上更復雜。經過多次閱讀和測試,我終於想出瞭如何做到這一點。

首先,創建自定義UIGestureRecognizer是對這一問題的妥善解決方案之一,但是當我做了我的空的自定義識別器的第一個測試,我犯了一個新手的錯誤:我忘了打電話給[super touches...:touches withEvent:event]每個方法我壓倒。這不會導致任何事情發生,因此我將識別器的狀態設置爲UIGestureRecognizerStateBegan,touchesBegan,這確實導致操作方法被調用一次,因此我相信我必須明確地管理狀態,這只是部分正確。實際上,如果您創建一個空的自定義識別器並在每個方法中調用適當的超級方法,那麼您的程序將按預期運行。在這種情況下,動作方法將在整個拖動動作中被調用。如果在touchesMoved中將識別器的狀態設置爲UIGestureRecognizerStateFailed,則事件也將按照預期鼓泡至超級視圖(本例中爲UITableView)。

的錯誤,我做了,我想其他人可能提出的,是想有設置手勢的狀態,當你繼承一個手勢識別的標準方法(即touchesBegantouchesMoved等)年表之間有直接的關係。沒有 - 至少,這不是一個確切的映射。你最好讓基本行爲保持原樣,只在必要時進行干預。因此,在我的情況下,一旦我確定用戶的拖動主要是垂直的,我只能在touchesMoved中做,我將手勢識別器的狀態設置爲UIGestureRecognizerStateFailed。這使識別器不在圖像中,並自動將全套事件轉發到全局視圖。

爲了簡潔起見,我忽略了大量通過這個練習學到的其他東西,但是要指出,關於這個主題的6,7本書,Matt Neuburg的編程IOS 4提供了迄今爲止這個問題的最好解釋。我希望在這個網站上允許轉介。我與作者或出版商沒有任何關係 - 只是感謝一個很好的解釋!

0

這可能是因爲響應者希望從頭到尾看到整個觸摸,而不僅僅是一個部分。通常情況下,-touchesBegan:...設置了一些狀態,然後在-touchesMoved中進行了修改......如果沒有先前收到-touchesBegan,則視圖無法獲得-touchesMoved ... 。甚至還有a note in the documentation,說,部分:

是處理觸摸所有視圖, 包括你自己,希望(或應該 預期)接收全觸摸事件 流。如果阻止響應者對象從 事件的某個階段接收 觸摸,則最終的行爲可能是 未定義,並且可能不合需要。

+0

@Caleb ...這是有道理的,但我認爲事件流是,命中測試視圖確實接收觸摸事件,直到手勢識別器識別手勢或將其狀態設置爲UIGestureRecognizerStateFailed。在後者的情況下,即失敗,難道你不希望命中測試視圖只是繼續處理觸摸嗎?如果不是,那麼在自定義手勢識別器失敗之後,如何獲得觸碰測試視圖來處理觸摸? – wayne