2009-08-15 94 views
6

說我有這樣的代碼:如何製作超級視圖攔截按鈕觸摸事件?

#import <UIKit/UIKit.h> 

@interface MyView : UIView 
@end 
@implementation MyView 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    // How can I get this to show up even when the button is touched? 
    NSLog(@"%@", [touches anyObject]); 
} 

@end 

@interface TestViewAppDelegate : NSObject <UIApplicationDelegate> 
{ 
    UIWindow *window; 
} 

@end 

@implementation TestViewAppDelegate 

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{ 
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

    MyView *view = [[MyView alloc] initWithFrame:[window frame]]; 
    [view setBackgroundColor:[UIColor whiteColor]]; 

    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [button setTitle:@"Hiya!" forState:UIControlStateNormal]; 
    [button setFrame:CGRectMake(100.0, 100.0, 200.0, 200.0)]; 
    [view addSubview:button]; 

    [window addSubview:view]; 
    [window makeKeyAndVisible]; 
} 


- (void)dealloc 
{ 
    [window release]; 
    [super dealloc]; 
} 

@end 

有沒有辦法攔截越來越發送到該按鈕的觸摸事件?我最終想要做的是製作一個UIView子類,當它檢測到滑動時會告訴它的視圖控制器(或委託,無論哪個),以便將下一個視圖控制器「推送」到堆棧上(類似於iPhone主屏幕)。我想這是第一步,但如果我不正確地處理這些問題,我會接受建議。

回答

1

感謝您的建議和豐富的答覆。我結束了使用this頁面上顯示的解釋:(在「技巧1:模擬照片應用程序刷/縮放/使用單個UIScrollView滾動」)。

16

我很希望看到其他的解決方案,但我知道最簡單的方法之一就是覆蓋以下兩種方法的UIView:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; 
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; 

這些方法被調用,以確定是否觸摸距離視圖或其任何子視圖的邊界,因此這是攔截觸摸然後傳遞它的好點。只要做任何你想要的東西,然後

return [super hitTest:point withEvent:event]; 

return [super pointInside:point withEvent:event]; 
+0

你不是指返回[superview hitTest:point withEvent:event]; – 2012-02-14 15:06:19

+0

'super'是對的,因爲你想調用類的父類方法,'superview'會跳過這個。 – keegan3d 2012-10-04 01:16:50

0

我相信你將不得不繼承的UIButton在這種情況下,並覆蓋到UIResponder的觸摸和動作事件的響應。然後,您可以將它們轉發給您想要假定UIButton子類可以訪問的任何對象。

在這種情況下,您會將它們傳遞給UIButton的超級視圖。

@interface MyButton : UIButton 
@end 

@implementation MyButton 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [[self superview] touchesMoved:touches withEvent:event]; 
} 

@end 

UIResponder documentation

+1

不幸的是,UIButton是一個類集羣。這意味着子類化幾乎是不可能的。 – 2009-08-19 22:56:14

+0

我不知道這是不好的。他確實提到了一些UIView子類,所以我只是在UIButton中使用它,因爲他在他的示例代碼中使用了它。 – criscokid 2009-08-20 04:25:50

4

本能會說:「子類UIButton的」,但UIButton的實際上是一類集羣(即對象的實際類型透明的變化取決於你想要做什麼樣的按鈕),這使得子類化非常困難。在重寫UIButton的時候,在這種方法上你可以做的不多。

當我需要解決一個幾乎相同的問題時,我想出了一個視圖,它使用組合來顯示代理UIView,但仍允許進行觸摸攔截。下面是它如何工作的:

@interface MyView : UIView { 
    UIView * visibleView; 
} 

- (id) initWithFrame:(CGRect)frame controlClass:(Class)class; 

@end 


@implementation MyView 

- (id) initWithFrame:(CGRect)frame controlClass:(Class)class { 
    if (self = [super initWithFrame:frame]) { 
    CGRect visibleViewFrame = frame; 
    visibleViewFrame.origin = CGPointZero; 
    visibleView = [[class alloc] initWithFrame:visibleViewFrame]; 
    [visibleView setUserInteractionEnabled:NO]; 
    [self addSubview:visibleView]; 

    [self setUserInteractionEnabled:YES]; 
    [self setBackgroundColor:[UIColor clearColor]]; 
    } 
    return self; 
} 

- (void) dealloc { 
    [visibleView removeFromSuperview]; 
    [visibleView release], visibleView = nil; 
    [super dealloc]; 
} 

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (someCondition == YES) { 
    [visibleView touchesBegan:touches withEvent:event]; 
    } 
} 

//and similar methods for touchesMoved:, touchesEnded:, etc 

@end 

的基本思想,這就是你要嵌入按鈕(或其他)到一個容器類(類似於你在你的問題中描述的)。但是,您正在禁用按鈕上的交互,這意味着當用戶點擊按鈕時,點擊事件將「落入」按鈕並進入包含超級視圖的按鈕(在此爲您的MyView實例)。從那裏,你可以適當地處理觸摸。如果你想讓按鈕「響應」觸摸,只需通過發送適當的UIResponder消息來允許按鈕。 (您可能需要在visibleView重新啓用userInteractionEnabled第一,雖然,我不能確定這一點。)

正如我上文所述,我已經使用這個方法(不是這個確切的實現,但這種模式)相當成功,當我需要在界面上有一個按鈕時,還要捕獲UITouch對象本身。

3

可能我建議使用這種方法來代替:

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] 
               initWithTarget:self 
               action:@selector(tapDetected:)]; 
    tapRecognizer.numberOfTapsRequired = 1; 
    tapRecognizer.numberOfTouchesRequired = 1; 

    [self.view addGestureRecognizer:tapRecognizer]; 

您可以從上海華做到這一點,沒有必要進行自定義UI元素。

+0

不錯,UITapGestureRecognizer與包含多個UILabel的UIView一起工作得很好。 – joelsand 2012-09-11 19:24:25