2012-04-21 36 views
0

我有一個子屏幕圖像的網格顯示在屏幕上;它基本上是以棋盤方式放置在屏幕上的一系列圖像。我只是想爲這些圖像子視圖中的每一個添加手勢識別器,以便當用戶觸摸其中一個圖像子視圖時,我可以檢索子視圖,即座標,標籤等。我的視圖層次結構如下所示:如何將手勢識別器添加到一系列子視圖?

  1. 超級視圖
  2. 一個gridContainer視圖
  3. 和每個個體子視圖 - 與圖像

看着蘋果文檔後,它好像我應該能夠手勢識別添加到gridContainer視圖和每個子視圖 - 與im年齡 - 應該繼承手勢識別器。到目前爲止,這是我嘗試過的:我已經在getter中分配了初始化網格容器視圖。另外,在getter中,我調用了我的createGesture方法,該方法應該將一個手勢識別器添加到gridContainer視圖。但是,我在運行時收到一個錯誤,指向我的actionSingleTap方法。它讀取EXC_BAD_EXCESS。 還值得注意的是,我不希望我的gridContainer視圖以外的視圖響應任何觸摸事件。預先感謝您的幫助。

這裏是我想要實現的代碼:

- (UIView *)gridContainerView 
{ 
    if (!_gridContainerView)_gridContainerView = [[UIView alloc] init]; 
    [self createGesture]; 
    return _gridContainerView; 
} 
- (void)createGesture 
{ 
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] 
             initWithTarget:self.gridContainerView 
             action:@selector(handleSingleTap:)]; 
    singleTap.numberOfTapsRequired = 1; 

    [self.gridContainerView addGestureRecognizer:singleTap]; 
} 

如果您需要看到任何額外的代碼,這是有道理的,請讓我知道。

編輯:包括handleSingleTap方法:

- (IBAction)handleSingleTap:(id)sender 
{ 
    CGPoint tapPoint = [sender locationInView:sender]; 
    NSLog(@"sender = %@",sender); 
    NSLog(@"tappoint = %@", tapPoint); 
} 

回答

4

要初始化您gridContainerView普通UIView。然後你附加一個手勢識別器(使用該視圖實例作爲目標)。然而,一個普通的UIView不執行handleSingleTap:,因此你會得到一個異常。

您應該創建一個(自定義UIView派生的)類,實現您需要該觸發手勢的選擇器。

+0

所以我應該創建一個自定義類,它是UIView的子視圖?我是否應該將我的gridContainerView放入此自定義類中,然後在我需要訪問時在控制器中調用它? – Scott 2012-04-21 13:29:41

+0

不是子視圖,而是子類。 – Till 2012-04-21 14:43:21

0

幾個問題馬上蝙蝠(甚至沒有處理您的手勢處理)。

您每次訪問gridContainerView時都會調用createGesture。您可能只希望在創建視圖時發生這種情況。此外,如果你看看createGesture,它回調到gridContainerView,其回調到createGesture,其回調到gridContainerView等

你可能想要更多的東西一樣......

- (UIView *)gridContainerView 
{ 
    if (!_gridContainerView) { 
     _gridContainerView = [[UIView alloc] init]; 
     [self createGesture]; 
    } 
    return _gridContainerView; 
} 

接下來,您正嘗試在視圖上調用handleSingleTap。你可能希望它在控制器上:initWithTarget:self。

- (void)createGesture 
{ 
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] 
             initWithTarget:self 
             action:@selector(handleSingleTap:)]; 
    singleTap.numberOfTapsRequired = 1; 

    [self.gridContainerView addGestureRecognizer:singleTap]; 
} 

你可能想重新考慮擁有兩個直接相互引用的獨立方法的智慧。但是,至少在我們對訪問者做出的改變之後,它應該是可以的。只要知道,如果在訪問器中添加更多代碼,則必須在調用createGesture之前完全設置該視圖。

+0

這些都是一些好點,但我的handleSingleTap方法似乎並沒有對觸摸事件做出響應。我編輯了上面的代碼,幷包含句柄單擊方法。任何想法爲什麼它沒有響應? – Scott 2012-04-21 13:43:59

0

一些事情。首先,你將gridContainerView實例化爲一個標準的UIView,然後發送消息:handleSingleTap:,它肯定不會響應。如果你想讓你的gridContainerView響應消息,你需要繼承UIView的子類,創建適當的方法,並將你的gridContainerView實例化爲子類。其次,就整體方法而言,我將爲gridContainerView創建子類(甚至可以稱之爲),並創建處理該手勢的方法。在該方法中,您可以使用UIGestureRecognizer方法locationInView:訪問被觸摸/點擊的點。使用這一點來確定在gridContainerView中哪個子視圖被點擊並執行相應的操作。要發現哪個子視圖被點擊,您可以遍歷子視圖並檢查每個子視圖以確定哪個包含點擊的點。有幾種方法的UIView有你可以用它來做到這一點:

pointInside:withEvent: hitTest:withEvent:

注意,您可以通過nil的事件。以上兩件事情略有不同。如果您只是測試點是否位於視圖中,請使用pointInside:withEvent,因爲它將返回BOOL。方法hitTest:withEvent將導致視圖搜索其所有子視圖,並返回其自身或其子視圖之一(如果該點在其界限之外,則返回nil)。 hitTest:withEvent可能會稍微多一點處理器密集度。此外,您也可以使用CGRectContainsPoint()進行測試。

相關問題