2009-08-15 11 views
6

Say mam ten kod:Jak wykonać zdarzenia dotykowego przechwytywania przycisków w interfejsie superview?

#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 

Czy istnieje jakiś sposób, aby przechwytywać zdarzenia dotykowe uzyskiwanie wysyłane do przycisku? Ostatecznie chciałbym zrobić podklasę UIView, która powie swojemu kontrolerowi widoku (lub deleguje, w zależności od tego), kiedy wykryje przesunięcie, aby mógł "wypchnąć" następny kontroler widoku na stos (podobny do ekranu głównego iPhone'a). Pomyślałem, że to pierwszy krok, ale jestem otwarty na sugestie, jeśli podejdę do tego niepoprawnie.

Odpowiedz

1

Dzięki za sugestie i odpowiedzi na pytania. Skończyło się na tym, że korzystałem z wyjaśnienia na stronie this: (w "Przesuwaniu i przesuwaniu aplikacji" Trick 1: Emulowanie zdjęć za pomocą jednego widoku UIScrollView ").

16

byłbym ciekaw innych rozwiązań, ale najprostszym sposobem, wiem to, aby zastąpić jedną z tych metod dwa UIView:

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

Metody te sprawdzony w celu ustalenia, czy dotyk jest w ramach granice widoku lub którykolwiek z jego podstron, więc jest to dobry punkt do przechwycenia dotyku, a następnie przekazania go dalej. Po prostu robić to, co kiedykolwiek chcesz, a następnie

return [super hitTest:point withEvent:event]; 

lub

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

nie masz na myśli powrotu [superview hitTest: point withEvent: event]; –

+0

'super' ma rację, ponieważ będziesz chciał wywołać metodę klasy nadrzędnej klasy,' superview' pominie to. – keegan3d

0

wierzę, trzeba by podklasy UIButton w tym przypadku i zastąpić reakcje na dotyk i ruch wydarzeń UIResponder użytkownika. Możesz następnie przesłać je do dowolnego obiektu, który chciałbyś założyć, że podklasa UIButton mogłaby do niego dotrzeć.

W takim przypadku należy przekazać je do superwizytu UIButton.

@interface MyButton : UIButton 
@end 

@implementation MyButton 

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

@end 

Zobacz UIResponder documentation

+1

UIButton to niestety klaster klasy. Oznacza to, że jest prawie niemożliwe do podklasy. –

+0

Nie wiedziałem, że to było takie złe. Wspomniał tylko o pewnej podklasie UIView, więc po prostu używałam Uibutton, ponieważ używał go w swoim przykładowym kodzie. – criscokid

4

Instynkt powie „podklasy UIButton”, ale UIButton jest faktycznie klaster klasy (czyli rzeczywisty typ obiektu przejrzysty zmienia się w zależności od rodzaju przycisku chcesz zrobić), co sprawia, że ​​niezwykle trudno jest podklasować. Bez przepisania UIButton, niewiele można zrobić w tym kierunku.

Kiedy potrzebowałem rozwiązać prawie identyczny problem, wymyśliłem widok, który używa kompozycji do wyświetlania UIView proxy, ale nadal pozwala na przechwycenie dotykiem. Oto jak to działa:

@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 

Podstawowym założeniem jest to, że jesteś osadzanie przycisku (lub cokolwiek) do klasy pojemnika (podobny do tego, co opisano w pytaniu). Jednak wyłączasz interakcję na przycisku, co oznacza, że ​​gdy użytkownik dotknie przycisku, zdarzenie dotknięcia "przejdzie" przez przycisk do przycisków zawierających widok z góry (w tym przypadku do instancji MyView). Stamtąd możesz odpowiednio przetworzyć dotyk. Jeśli chcesz, aby przycisk "reagował" na dotyk, po prostu pozwól przyciskowi to zrobić, wysyłając odpowiedni komunikat UIResponder. (Ty może potrzeby, aby ponownie włączyć userInteractionEnabled na visibleView pierwszy, choć. Jestem pewny, że.)

Jak już wspomniano powyżej, użyłem tego podejścia (nie dokładnie ten realizacji, ale ten wzór) całkiem dobrze, gdy potrzebowałem mieć przycisk na interfejsie, ale także uchwycić obiekt UITouch.

3

Mogę zaproponować zastosowanie tej metody zamiast:

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

    [self.view addGestureRecognizer:tapRecognizer]; 

Można to zrobić z SuperView, nie ma potrzeby, aby niestandardowych elementów UI.

+0

Dobrze, UITapGestureRecognizer działał świetnie z UIView, który zawiera kilka UILabel. – joelsand

Powiązane problemy