2009-08-15 20 views
6

Nói rằng tôi có mã này:Làm cách nào để tạo sự kiện chạm vào nút đánh chặn giám sát?

#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 

Có cách nào để ngăn chặn những sự kiện liên lạc bị gửi đến các nút? Những gì tôi muốn cuối cùng làm là làm cho một lớp con UIView sẽ nói cho bộ điều khiển xem của nó (hoặc đại biểu, tùy theo điều kiện) khi nó phát hiện một swipe để nó có thể "đẩy" bộ điều khiển xem tiếp theo vào ngăn xếp (tương tự như màn hình chính iPhone). Tôi đã nhận ra đây là bước đầu tiên, nhưng tôi mở lời đề xuất nếu tôi tiếp cận điều này không chính xác.

Trả lời

1

Cảm ơn các đề xuất và trả lời thông tin. Tôi đã kết thúc chỉ bằng cách sử dụng giải thích được hiển thị trên trang this: (trong "Thủ thuật 1: Thi đua ứng dụng Ảnh vuốt/thu phóng/cuộn bằng một UIScrollView duy nhất").

16

Tôi muốn được quan tâm khi thấy các giải pháp khác, nhưng cách dễ nhất tôi biết là để ghi đè lên một trong những phương pháp hai UIView:

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

Những phương pháp này được gọi là để xác định xem các liên lạc nằm trong giới hạn của chế độ xem hoặc bất kỳ tiểu sử nào của nó, do đó, đây là điểm tốt để chặn liên lạc và sau đó vượt qua nó. Chỉ cần làm những gì mà bạn muốn, và sau đó

return [super hitTest:point withEvent:event]; 

hoặc

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

bạn không có nghĩa là trả lại [superview hitTest: point withEvent: event]; –

+0

'super' là đúng bởi vì bạn sẽ muốn gọi các lớp cha mẹ lớp phương pháp,' superview' sẽ bỏ qua này. – keegan3d

0

Tôi tin rằng bạn sẽ phải phân lớp UIButton trong trường hợp này và ghi đè lên các phản ứng để UIResponder của cảm ứng và chuyển động sự kiện. Sau đó bạn có thể chuyển tiếp chúng đến bất kỳ đối tượng nào bạn muốn giả định lớp con UIButton có thể nhận được nó.

Trong trường hợp này, bạn sẽ chuyển chúng cho người giám sát của UIButton.

@interface MyButton : UIButton 
@end 

@implementation MyButton 

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

@end 

Xem UIResponder documentation

+1

UIButton là một nhóm lớp, không may. Điều này có nghĩa là hầu như không thể phân lớp. –

+0

Tôi không biết rằng điều đó thật tệ. Ông đã đề cập đến chỉ là một số UIView subclass vì vậy tôi đã chỉ đi với UIButton kể từ khi ông sử dụng nó trong mã ví dụ của mình. – criscokid

4

Instinct sẽ nói "lớp con UIButton", nhưng UIButton thực sự là một cụm lớp (ví dụ, các loại thực tế của đối tượng một cách minh bạch thay đổi tùy thuộc vào loại nút của bạn muốn chắc), điều này khiến cho phân lớp trở nên cực kỳ khó khăn. Viết tắt của UIButton, không có nhiều bạn có thể làm trên phương pháp đó.

Khi tôi cần giải quyết một vấn đề gần như giống hệt nhau, tôi đã đưa ra một chế độ xem sử dụng bố cục để hiển thị UIView proxy, nhưng vẫn cho phép chặn liên lạc. Dưới đây là cách hoạt động:

@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 

Ý tưởng cơ bản này là bạn đang nhúng nút (hoặc bất kỳ) vào một lớp container (tương tự như những gì bạn mô tả trong câu hỏi của bạn). Tuy nhiên, bạn đang vô hiệu hóa tương tác trên nút, có nghĩa là khi người dùng nhấn vào nút, sự kiện nhấn sẽ "rơi qua" nút và vào các nút chứa superview (trong trường hợp này là MyView của bạn). Từ đó, bạn có thể xử lý các liên lạc một cách thích hợp. Nếu bạn muốn nút "phản hồi" khi chạm, chỉ cần cho phép nút thực hiện việc đó bằng cách gửi thông báo UIResponder thích hợp. (Tuy nhiên, bạn có thể cần phải bật lại userInteractionEnabled trên visibleView trước. Tôi không chắc điều đó.)

Như tôi đã nói ở trên, tôi đã sử dụng phương pháp này (không thực hiện chính xác, nhưng mẫu này) khá thành công, khi tôi cần phải có một nút trên giao diện, nhưng cũng chụp chính đối tượng UITouch.

3

Có thể tôi khuyên bạn nên sử dụng phương pháp này thay vì:

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

    [self.view addGestureRecognizer:tapRecognizer]; 

Bạn có thể làm điều này từ SuperView, không cần phải làm cho các yếu tố tùy chỉnh giao diện người dùng.

+0

Đẹp, UITapGestureRecognizer làm việc tuyệt vời với một UIView có chứa một số UILabel của. – joelsand

Các vấn đề liên quan