wake-up-neo.com

Wie deaktiviere ich die Berührungseingabe für alle Ansichten außer der obersten Ansicht?

Ich habe eine Ansicht mit mehreren Teilansichten. Wenn ein Benutzer auf eine Unteransicht tippt, wird die Unteransicht vergrößert, um den größten Teil des Bildschirms abzudecken. Einige der anderen Unteransichten werden jedoch weiterhin darunter angezeigt.

Ich möchte, dass meine App Berührungen der anderen Unteransichten ignoriert, wenn eine der Unteransichten auf diese Weise "erweitert" wird. Gibt es einen einfachen Weg, dies zu erreichen? Ich kann Code schreiben, um damit umzugehen, aber ich hatte gehofft, dass es einen einfacheren eingebauten Weg gibt.

42
MusiGenesis

Ich hoffe das hilft...

[[yourSuperView subviews]
   makeObjectsPerformSelector:@selector(setUserInteractionEnabled:)
   withObject:[NSNumber numberWithBool:FALSE]];

dadurch wird die Benutzerinteraktion für die unmittelbaren Unteransichten einer Ansicht deaktiviert. Geben Sie dann der einzigen gewünschten Ansicht die Benutzerinteraktion

yourTouchableView.setUserInteraction = TRUE;

BEARBEITEN:

Es scheint, dass in iOS das Deaktivieren von userInteraction in einer übergeordneten Ansicht userInteraction in ihren untergeordneten Ansichten nicht deaktiviert. Also der obige Code (ich meine den mitmakeObjectsPerformSelector:) funktioniert nur zum Deaktivieren von userInteraction der unmittelbaren Teilansichten eines Elternteils.

Sehen Sie sich die Antwort von Benutzer madewulf an, die rekursiv alle Unteransichten abruft, und deaktivieren Sie die Benutzerinteraktion für alle. Oder wenn Sie die Benutzerinteraktion dieser Ansicht an vielen Stellen im Projekt deaktivieren müssen, können Sie UIView kategorisieren, um diese Funktion hinzuzufügen.

@interface UIView (UserInteractionFeatures)
-(void)setRecursiveUserInteraction:(BOOL)value;
@end

@implementation UIView(UserInteractionFeatures)
-(void)setRecursiveUserInteraction:(BOOL)value{
    self.userInteractionEnabled =   value;
    for (UIView *view in [self subviews]) {
        [view setRecursiveUserInteraction:value];
    }
}
@end

Jetzt können Sie anrufen

[yourSuperView setRecursiveUserInteraction:NO];

Auch der Vorschlag von user @ lxt, eine unsichtbare Ansicht über alle Ansichten zu setzen, ist eine andere Möglichkeit.

53
Krishnabhadra

Hierfür gibt es verschiedene Möglichkeiten. Sie können alle anderen Unteransichten durchlaufen und userInteractionEnabled = NO, aber das ist nicht ideal, wenn Sie viele andere Ansichten haben (Sie müssten sie schließlich alle nachträglich erneuern).

Die Art und Weise, wie ich das mache, ist, eine unsichtbare UIView zu erstellen, die die Größe des gesamten Bildschirms hat und alle Berührungen daran hindert, zu den anderen Ansichten zu gelangen. Manchmal ist dies buchstäblich unsichtbar, manchmal setze ich es auf Schwarz mit einem Alpha-Wert von 0,3 oder so.

Wenn Sie Ihre Haupt-Unteransicht erweitern, um den Bildschirm auszufüllen, können Sie diese blockierende UIView dahinter hinzufügen (mit insertSubview: belowSubview:). Wenn Sie Ihre erweiterte Unteransicht minimieren, können Sie die unsichtbare UIView aus Ihrer Hierarchie entfernen.

Also nicht ganz eingebaut, aber ich denke der einfachste Ansatz. Ich bin mir nicht sicher, ob es das war, woran du schon gedacht hast, hoffentlich war es hilfreich.

46
lxt

Hüten Sie sich vor dem Code, den Krishnabhadra hier als Lösung gegeben hat:

[[yourSuperView subviews]makeObjectsPerformSelector:@selector(setUserInteractionEnabled:) withObject:[NSNumber numberWithBool:FALSE]];

Dies funktioniert nicht in allen Fällen, da [Ihre SuperView-Unteransichten] nur die direkten Unteransichten der Übersicht enthält. Damit es funktioniert, müssen Sie in allen Unteransichten rekursiv iterieren:

-(void) disableRecursivelyAllSubviews:(UIView *) theView
{
    theView.userInteractionEnabled = NO;
    for(UIView* subview in [theView subviews])
    {
        [self disableRecursivelyAllSubviews:subview];
    }
}

-(void) disableAllSubviewsOf:(UIView *) theView
{
    for(UIView* subview in [theView subviews])
    {
        [self disableRecursivelyAllSubviews:subview];
    }
} 

Nun wird ein Aufruf von disableAllSubviewsOf das tun, was Sie tun wollten.

Wenn Sie einen tiefen Stapel von Ansichten haben, ist die Lösung von lxt wahrscheinlich besser.

8
madewulf

Ich würde dies tun, indem ich eine benutzerdefinierte transparente Schaltfläche mit demselben Rahmen wie die superView setze. Und dann würde ich oben auf diese Schaltfläche eine Ansicht setzen, die Benutzerberührungen akzeptieren sollte. Der Knopf schluckt alle Berührungen und Ansichten dahinter erhalten keine Berührungsereignisse, aber die Ansicht über dem Knopf empfängt Berührungen normal.

Etwas wie das:

- (void)disableTouchesOnView:(UIView *)view {
    UIButton *ghostButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)];
    [ghostButton setBackgroundColor:[UIColor clearColor]];
    ghostButton.tag = 42; // Any random number. Use #define to avoid putting numbers in code.

    [view addSubview:ghostButton];
}

Und eine Methode zum Aktivieren von parentView.

- (void)enableTouchesOnView:(UIView *)view {
    [[view viewWithTag:42] removeFromSuperview];
}

Um also alle Ansichten in parentViev hinter yourView zu deaktivieren, würde ich Folgendes tun:

YourView *yourView = [[YourView alloc] initWithCustomInitializer];
// It is important to disable touches on the parent view before adding the top most view.
[self disableTouchesOnView:parentView];
[parentView addSubview:yourView];
5
JPetric

Gerade parentView.UserInteractionEnabled = NO wird die Arbeit machen. Die übergeordnete Ansicht wird deaktivieren Benutzerinteraktion für alle Unteransichten der Ansicht. Aber aktivieren nicht aktivieren alle Unteransichten (standardmäßig ist UIImageView nicht interaktiv). Eine einfache Möglichkeit besteht darin, die übergeordnete Ansicht zu finden und den obigen Code zu verwenden. Es ist nicht erforderlich, alle Unteransichten zu iterieren, um eine Auswahl durchzuführen.

4
musixlemon

Ich werde meine 2 Cent für dieses Problem geben. Iterativ userInteractionEnabled = false ausführen, das ist eine Möglichkeit. Eine andere Möglichkeit ist das Hinzufügen einer UIView wie folgt.

EZEventEater.h

#import <UIKit/UIKit.h>
@interface EZEventEater : UIView
@end

EZEventEater.m

#import "EZEventEater.h"
@implementation EZEventEater

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor clearColor];
        self.userInteractionEnabled = false;
    }
    return self;
}


- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   //EZDEBUG(@"eater touched");
}

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

}

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

}

In Ihrem Code fügen Sie die EZEventEater-Ansicht hinzu, um alle Ansichten abzudecken, in denen Sie das Berührungsereignis blockieren können. Wenn Sie das Berührungsereignis für diese Ansichten blockieren möchten, rufen Sie einfach an

eater.userInteractionEnabled = YES;

Hoffe das hilfreich.

2
tianwalker

Fügen Sie Ihrer "Hintergrundansicht" einen TapGestureRecognizer hinzu (der durchscheinende, der Ihre normale Benutzeroberfläche "ausgraut"), und setzen Sie ihn auf "Berührungen in Ansicht abbrechen", ohne eine Aktion hinzuzufügen.

let captureTaps = UITapGestureRecognizer()
captureTaps.cancelsTouchesInView = true
dimmedOverlay?.addGestureRecognizer(captureTaps)
1
Robert Atkins

Für meine App ist es meines Erachtens ausreichend, die Navigation zu anderen Registerkarten der App zu deaktivieren (für eine begrenzte Zeit, während ich etwas bearbeite):

self.tabBarController.view.userInteractionEnabled = NO;

Außerdem habe ich den aktuellen Ansichtscontroller deaktiviert.

self.view.userInteractionEnabled = NO;

(Übrigens hatten die hier vorgeschlagenen rekursiven Lösungen in meiner App merkwürdige Auswirkungen. Die Deaktivierung scheint gut zu funktionieren, aber die erneute Aktivierung hat merkwürdige Auswirkungen - einige der Benutzeroberflächen wurden nicht erneut aktiviert.).

0
Chris Prince

setUserInteractionEnabled = NO in der Ansicht, die Sie deaktivieren möchten

0
Kirby Todd