iOS - alle Berührungen durch eine Ansicht weiterleiten


75

Ich habe eine Ansicht überlagert auf vielen anderen Ansichten. Ich benutze nur den Overall, um einige Berührungen auf dem Bildschirm zu erkennen, aber ansonsten möchte ich nicht, dass die Ansicht das Verhalten anderer Ansichten unterbindet, die Scrollviews usw. sind. Wie kann ich alle Berührungen weiterleiten? diese Überlagerungsansicht? Es ist eine Unterkalkulation von UIView.

0

versuchen, etwas so ...

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

Der obige Code, in Ihrem touchesBegan Verfahren zum Beispiel der Berührungen, um alle der Subviews Sicht passieren würde.

@interface SomeViewSubclass : UIView { 

    id forwardableTouchee; 

} 
@property (retain) id forwardableTouchee; 

Stellen Sie sicher, zu synthetisieren:

+6

Das Problem bei diesem Ansatz AFAIK ist, dass berühren die Klassen des UIKit Rahmen wird am häufigsten zu übermitteln versucht hat keine bewirken. Laut Apples Dokumentation sind UIKit-Framework-Klassen nicht dafür ausgelegt, Berührungen zu erhalten, bei denen die View-Eigenschaft auf eine andere Ansicht eingestellt ist. Dieser Ansatz funktioniert also hauptsächlich für benutzerdefinierte Unterklassen von UIView. 02 mär. 112011-03-02 23:05:35


4

Wenn die Ansicht, um die Noten zu übermitteln will nicht geschieht ein Subview/Super sein, können Sie eine benutzerdefinierte Eigenschaft in Ihrer UIView Unterklasse wie so einrichten es in .m:

@synthesize forwardableTouchee; 

Und dann gehören folgende in jedem Ihrer UIResponder Methoden wie:

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

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

} 

Wo auch immer Sie Ihre UIView instanziiert, stellen die forwardableTouchee Eigenschaft zu, was sehen Sie die Ereignisse möchten weitergeleitet an:

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

75

Für berührt von einer Überlagerungsansicht auf die Ansichten unter vorbei, implementieren Sie die folgenden Verfahren in die UIView:

Objective-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

Ich habe das gleiche Problem, aber was ich will ist, wenn ich mit der Geste Zoomen/Drehen/Bewegen der Ansicht, dann sollte es ja zurückkehren und für den Rest Event sollte es keine zurückgeben, wie kann ich das erreichen? 12 aug. 132013-08-12 06:27:33


58
myWebView.userInteractionEnabled = NO; 

war alles was ich brauchte!


38

Dies ist ein alter Thread, aber es kam auf einer Suche, so dass ich dachte, ich würde meine 2c hinzufügen. Ich habe eine Abdeckung UIView mit Subviews, und wollen nur die Berührungen abzufangen, die eine der Subviews getroffen, so dass ich modifizierte PixelCloudSt Antwort auf

-(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

Sie müssen eine benutzerdefinierte UIView-Unterklasse (oder eine Unterklasse einer anderen UIView-Unterklasse wie UIImageView oder was auch immer) erstellen und diese Funktion überschreiben. Im Wesentlichen kann die Unterklasse ein vollständig leeres "@interface" in der .h-Datei haben, und die obige Funktion ist der gesamte Inhalt der "@implementation". 07 mär. 142014-03-07 16:01:14


-1

Wie @PixelCloudStv vorgeschlagen, wenn Sie von einer Ansicht berührt werfen wollen ein anderer aber mit einigen zusätzlichen Kontrolle über diesen Prozess - Unterklasse UIView

// header

@interface TouchView : UIView 

@property (assign, nonatomic) CGRect activeRect; 

@end 

// Implementierung

#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 

Nach in interfaceBuilder nur Klasse der Ansicht auf TouchView setzen und aktiv rect mit Ihrem Rect. Sie können auch andere Logik ändern und implementieren.


3

Ich hatte ein ähnliches Problem mit einem UIStackView (könnte aber jede andere Ansicht sein). Meine Konfiguration war die folgende: View controller with containerView and StackView

Es ist ein klassischer Fall, wo ich einen Container haben, die mit den Tasten auf der Seite in den Hintergrund gestellt werden musste. Für Layoutzwecke habe ich die Schaltflächen in eine UIStackView eingefügt, aber jetzt berührt der mittlere (leere) Teil des StackView :-(

Was ich getan habe, ist eine Unterklasse von UIStackView mit einer Eigenschaft zu erstellen, die den SubView definiert, der sein sollte berührbar Jetzt wird jede Berührung der Seitentasten (die im Array * viewsWithActiveTouch * enthalten sind) den Schaltflächen zugewiesen, während jede Berührung der Stapelansicht an anderer Stelle als diese Ansichten nicht abgefangen und daher an irgendeine Stelle übergeben wird unterhalb der Stapelansicht.

/** 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

Verbesserte Version von @fresidue Antwort. Sie können diese UIView Unterklasse als transparente Sicht vorbei berührt verwenden ou verdeckt seine Unteransicht. Die Umsetzung in 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 

und in 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) 
    }) 
    } 
}