iOS - przesyła wszystkie dotknięcia przez widok


75

Mam widok nałożony na wiele innych widoków. Używam tylko przesłony do wykrycia pewnej liczby dotknięć na ekranie, ale poza tym nie chcę, aby widok zatrzymywał zachowanie innych widoków pod spodem, które są przewijane, itp. Jak mogę przesłać wszystkie dotknięcia przez ten widok nakładki? Jest to podkategoria UIView.

0

spróbować czegoś takiego ...

for (UIView *view in subviews) 
    [view touchesBegan:touches withEvent:event]; 

Kod powyżej, w swoim sposobie touchesBegan np minie ostatnie poprawki do wszystkich subviews widzenia.

+6

Problem z tym podejściem AFAIK jest to, że próby przekazania poprawki do klas UIKit ram będzie najczęściej nie mają efekt. Według dokumentacji Apple klasy UIKit nie są zaprojektowane do otrzymywania dotknięć, które mają właściwość view ustawioną na inny widok. Tak więc to podejście działa głównie dla niestandardowych podklas UIView. 02 mar. 112011-03-02 23:05:35


4

Jeśli widok chcesz przekazać ostatnie poprawki do nie zdarza się być podrzędny/Superview, można ustawić właściwość niestandardową w UIView podklasy tak:

@interface SomeViewSubclass : UIView { 

    id forwardableTouchee; 

} 
@property (retain) id forwardableTouchee; 

Upewnij syntetyzować to w .m:

@synthesize forwardableTouchee; 

a następnie dołączyć następujące w dowolnych metod UIResponder takich jak:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    [self.forwardableTouchee touchesBegan:touches withEvent:event]; 

} 

Gdziekolwiek instancję swoje UIView, ustaw właściwość forwardableTouchee aby cokolwiek widok chcesz zdarzenia mają być przekazywane:

SomeViewSubclass *view = [[[SomeViewSubclass alloc] initWithFrame:someRect] autorelease]; 
    view.forwardableTouchee = someOtherView; 

75

Na przejściu akcenty z widokiem nakładki do poglądów pod spodem, wdrożyć następujące metody w UIView:

Cel C:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { 
    NSLog(@"Passing all touches to the next view (if any), in the view stack."); 
    return NO; 
} 

Swift:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 
    print("Passing all touches to the next view (if any), in the view stack.") 
    return false 
} 
+2

Mam ten sam problem, ale to, czego chcę, to jeśli powiększam/obracam/poruszam widok z gestem, to powinien on zwracać tak, a dla odpoczynku, powinien zwracać nie, jak mogę to osiągnąć? 12 sie. 132013-08-12 06:27:33


58
myWebView.userInteractionEnabled = NO; 

było wszystko, co potrzebne!


38

Jest to stary wątek, ale wpadł na poszukiwaniu, więc pomyślałam, że dodam moje 2c. Mam UIView pokrycie subviews, a jedynie chcą przechwycić akcenty, które nawiedziły jeden z subviews, więc modyfikować odpowiedź PixelCloudSt do

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    for (UIView* subview in self.subviews) { 
     if ([subview hitTest:[self convertPoint:point toView:subview] withEvent:event] != nil) { 
      return YES; 
     } 
    } 
    return NO; 
} 
+1

Należy utworzyć niestandardową podklasę UIView (lub podklasę dowolnej innej podklasy UIView, takiej jak UIImageView lub coś podobnego) i zastąpić tę funkcję. Zasadniczo, podklasa może mieć całkowicie pusty "@interface" w pliku .h, a powyższa funkcja jest całą zawartością "@implementation". 07 mar. 142014-03-07 16:01:14


-1

Jak sugeruje @PixelCloudStv jeśli chcesz rzucić dotknął z jednego celu inny, ale z pewną dodatkową kontrolę nad tym procesem - podklasy UIView

// nagłówek

@interface TouchView : UIView 

@property (assign, nonatomic) CGRect activeRect; 

@end 

// implementacja

#import "TouchView.h" 

@implementation TouchView 

#pragma mark - Ovverride 

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    BOOL moveTouch = YES; 
    if (CGRectContainsPoint(self.activeRect, point)) { 
     moveTouch = NO; 
    } 
    return moveTouch; 
} 

@end 

Później w interfaceBuilder wystarczy ustawić klasę View na TouchView i ustawić active rect za pomocą rect. Również możesz zmienić i wdrożyć inną logikę.


3

Miałem podobny problem z UIStackView (ale może być dowolny inny widok). Moja konfiguracja była następująca: View controller with containerView and StackView

Jest to klasyczny przypadek, w którym mam pojemnik, który potrzebne do umieszczenia w tle, za pomocą przycisków na stronie. Dla celów układu, włączyłem przyciski w UIStackView, ale teraz środkowa (pusta) część przechwytywanych widoków stackView :-(

To, co zrobiłem, to stworzyć podklasę UIStackView z właściwością definiującą subView, która powinna być Teraz dowolne dotknięcie bocznych przycisków (zawartych w * viewsWithActiveTouch * array) zostanie przypisane do przycisków, podczas gdy dowolne dotknięcie widoku stosu poza tymi widokami nie zostanie przechwycone, a zatem przekazane do tego, co jest poniżej widoku stosu.

/** Subclass of UIStackView that does not accept touches, except for specific subviews given in the viewsWithActiveTouch array */ 
class NoTouchStackView: UIStackView { 

    var viewsWithActiveTouch: [UIView]? 

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 

    if let activeViews = viewsWithActiveTouch { 
     for view in activeViews { 
      if CGRectContainsPoint(view.frame, point) { 
       return view 

      } 
     } 
    } 
    return nil 
    } 
} 

14

ulepszona wersja odpowiedzi @fresidue. można użyć tej UIView podklasy jako przejrzysty widok przechodzącej dotyka ou w jego wywiadzie. Wdrożenie w Objective-C:

@interface PassthroughView : UIView 

@end 

@implementation PassthroughView 

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    for (UIView *view in self.subviews) { 
     if (!view.hidden && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) { 
      return YES; 
     } 
    } 
    return NO; 
} 

@end 

aw SWIFT:

class PassthroughView: UIView { 
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 
    return subviews.contains(where: { 
     !$0.isHidden && $0.point(inside: self.convert(point, to: $0), with: event) 
    }) 
    } 
}