Frage

, dies zu tun (ebay auf ipad zum Beispiel)

Ich mag eine FormSheetPresentation modal View-Controller entlassen, wenn die Benutzer Hähne außerhalb der modalen Ansicht ... Ich habe eine Reihe von Anwendungen gesehen, aber ich kann nicht herausfinden, wie da die unter Ansichten sind Behinderte aus berührt, wenn modale Ansichten wie diese angezeigt werden (werden sie es als popover präsentiert vielleicht?) ... jemand irgendwelche Vorschläge?

War es hilfreich?

Lösung

Ich bin ein Jahr zu spät, aber das ist ziemlich einfach zu tun.

Haben Sie Ihre modal View-Controller eine Gestenerkenner an das Fenster der Ansicht anhängen:

UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];

[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];
[recognizer release];

Der Umgang Code:

- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
     {
       CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window

 //Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.

        if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) 
        {
           // Remove the recognizer first so it's view.window is valid.
          [self.view.window removeGestureRecognizer:sender];
          [self dismissModalViewControllerAnimated:YES];
        }
     }
}

Das ist es. HIG verdammt wird, ist dies ein nützliches und oft intuitives Verhalten ist.

Andere Tipps

Die anderen Anwendungen sind nicht Modal mit Ansichten, wenn sie der Ansicht zulassen, indem Sie außerhalb davon zu entlassen. UIModalPresentationFormSheets kann nicht auf diese Weise zurückzuweisen. (Noch, in der Tat kann jeder UIModal in SDK3.2). Nur der UIPopoverController kann durch Klicken außerhalb des Bereichs abzuweisen. Es ist durchaus möglich (wenn auch gegen Apples iPad HIG) für den App-Entwickler, um den Hintergrund-Bildschirm hat beschattet und angezeigt dann die UIPopoverController so dass es wie ein UIModalPresentationFormSheets (oder anderes UIModal View) aussieht.

  

[...] UIModalPresentationCurrentContext Stil lässt einen View-Controller die Präsentation Stil seiner Eltern übernehmen. In jeder modalen Ansicht zeigen die gedimmt Bereiche die zugrunde liegenden Inhalte aber nicht Abgriffe in diesen Inhalten ermöglichen. Deshalb, im Gegensatz zu einem popover, Ihre modal Ansichten müssen noch Kontrollen haben, die dem Benutzer erlauben, die modale Ansicht zu schließen.

Sehen Sie die iPadProgrammingGuide auf der Entwickler-Website für weitere Informationen (Seite 46 - „Konfigurieren der Präsentationsstil für Modal Views“)

Für iOS 8, müssen Sie sowohl die UIGestureRecognizer implementieren, und tauschen Sie das (x, y) Koordinaten der angezapften Lage, wenn in Querformat. Nicht sicher, ob dies zu einem iOS 8 Fehler zurückzuführen ist.

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // add gesture recognizer to window

    UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];
    [recognizer setNumberOfTapsRequired:1];
    recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
    [self.view.window addGestureRecognizer:recognizer];
    recognizer.delegate = self;
}

- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded) {

        // passing nil gives us coordinates in the window
        CGPoint location = [sender locationInView:nil];

        // swap (x,y) on iOS 8 in landscape
        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
            if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
                location = CGPointMake(location.y, location.x);
            }
        }

        // convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.
        if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) {

            // remove the recognizer first so it's view.window is valid
            [self.view.window removeGestureRecognizer:sender];
            [self dismissViewControllerAnimated:YES completion:nil];
        }
    }
}


#pragma mark - UIGestureRecognizer Delegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return YES;
}

Der obige Code funktioniert super, aber ich würde die if-Anweisung ändern,

    if (!([self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil] || [self.navigationController.view pointInside:[self.navigationController.view convertPoint:location fromView:self.navigationController.view.window] withEvent:nil]))

    {
        // Remove the recognizer first so it's view.window is valid.
        [self.view.window removeGestureRecognizer:sender];
        [self dismissModalViewControllerAnimated:YES];
    }

Dies stellt sicher, können Sie immer noch interact mit der Navigationsleiste, sonst Antippen der modale Ansicht entlässt.

Antwort für iOS aktualisiert 8

Offenbar in iOS 8, die UIDimmingView hat einen Anzapfung Gestenerkenner, die interferiert mit der ersten Implementierung, so dass wir es ignorieren und es nicht scheitern müssen.


Dies ist das Zeitalter der Geschwindigkeit, die meisten sind so wahrscheinlich Kopieren Sie einfach den Code oben .. Aber ich leiden unter OCD, wenn es um Code kommt, leider.

Hier ist eine modulare Lösung, die Danilo Campos Antwort verwendet mit Kategorien . Es ist auch löst ein wichtiger Fehler, die auftreten können, wenn Sie Ihre modal durch andere Mittel zu entlassen, wie erwähnt .

. Hinweis: Die if-Anweisungen sind da, weil ich die View-Controller für iPhone und iPad, und nur das iPad muss / unregister registrieren

UPDATE: Der Kern aktualisiert wurde, da es nicht funktioniert richtig mit dem ehrfürchtigen

Kopieren Sie diesen Code in Ihrem ModalViewController einfügen:

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    //Code for dissmissing this viewController by clicking outside it
    UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];
    [recognizer setNumberOfTapsRequired:1];
    recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
    [self.view.window addGestureRecognizer:recognizer];

}

- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
    {
        CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window

        //Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.

        if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])
        {
            // Remove the recognizer first so it's view.window is valid.
            [self.view.window removeGestureRecognizer:sender];
            [self dismissModalViewControllerAnimated:YES];
        }
    }
}

Very important: Wenn Sie irgendeine andere Art und Weise müssen schließen Sie Ihren modalen Popup-Fenster , vergessen Sie nicht den Hahn Gestenerkenner zu entfernen!

Ich habe vergessen, dies und bekam verrückt Abstürze später, da der Hahn Erkennungs immer noch Ereignisse feuern.

Nach Apples iOS HIG, 1. die modale Ansicht nicht über diese Fähigkeit ohne Eingabe auf sich selbst entlassen zu werden; 2. Verwenden modalen Ansicht in der Situation, dass eine Benutzereingabe erforderlich ist.

Verwenden UIPresentationController statt:

- (void)presentationTransitionWillBegin
{
    [super presentationTransitionWillBegin];
    UITapGestureRecognizer *dismissGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(dismissGestureTapped:)];
    [self.containerView addGestureRecognizer:dismissGesture];

    [[[self presentedViewController] transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    } completion:nil];
}
- (void) dismissGestureTapped:(UITapGestureRecognizer *)sender{
    if (sender.state==UIGestureRecognizerStateEnded&&!CGRectContainsPoint([self frameOfPresentedViewInContainerView], [sender locationInView:sender.view])) {
        [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
    }
}

Geändert von LookInside Beispiel

Dies funktioniert für mich für ios7 eine 8 und Navigationsleiste.

Wenn Sie nicht über die Navigationsleiste müssen nur entfernen location2 und zweite Bedingung in der if-Anweisung nach den Rohren.

@MiQUEL sollte dies auch für Sie arbeiten

- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
    {
        CGPoint location1 =  [sender locationInView:self.view];
        CGPoint location2 = [sender locationInView:self.navigationController.view];

        if (!([self.view pointInside:location1 withEvent:nil] || [self.navigationController.view pointInside:location2 withEvent:nil])) {
            [self.view.window removeGestureRecognizer:self.recognizer];
            [self dismissViewControllerAnimated:YES completion:nil];
        }
    }
}

Edit: Sie können auch eine Gestenerkenner Delegat für diese und andere oben genannten Lösungen zur Arbeit sein müssen. Machen Sie es wie so:

@interface CommentTableViewController () <UIGestureRecognizerDelegate>

setzen Sie sich als Delegierter für den Erkenner:

self.recognizer.delegate = self;

und implementieren diese Delegatmethode:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

Es ist ziemlich machbar.

Werfen Sie einen Blick hier

https://stackoverflow.com/a/26016458/4074557

Es ist ein Navigation (modal), dass Auto für ipad entlassen (wenn Sie außerhalb tippen)

Verwenden des Viewcontroller im Innern.

Hope es hilft.

Ich weiß, es ist spät, aber denken Sie daran mit CleanModal (getestet mit iOS 7 und 8).

https://github.com/orafaelreis/CleanModal

Sie können mit MZFormSheetController wie folgt aus:

MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithSize:customSize viewController:presentedViewController];
formSheet.shouldDismissOnBackgroundViewTap = YES;
[presentingViewController mz_presentFormSheetController:formSheet animated:YES completionHandler:nil];

In Swift 2 / Xcode Version 7.2 (7C68) der folgende Code für mich gearbeitet.

Achtung: Dieser Code soll, hier in der ViewController.swift Datei des dargebotenen Formblatt oder Seite Blattes gestellt werden: „PageSheetViewController.swift“

class PageSheetViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidAppear(animated: Bool) {
        let recognizer = UITapGestureRecognizer(target: self, action:Selector("handleTapBehind:"))
        recognizer.delegate = self
        recognizer.numberOfTapsRequired = 1
        recognizer.cancelsTouchesInView = false
        self.view.window?.addGestureRecognizer(recognizer)
    }

    func gestureRecognizer(sender: UIGestureRecognizer,
        shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
            return true
    }

    func handleTapBehind(sender:UIGestureRecognizer) {
        if(sender.state == UIGestureRecognizerState.Ended){
            var location:CGPoint = sender.locationInView(nil)

            // detect iOS Version 8.0 or greater
            let Device = UIDevice.currentDevice()
            let iosVersion = Double(Device.systemVersion) ?? 0
            let iOS8 = iosVersion >= 8

            if (iOS8) {
                // in landscape view you will have to swap the location coordinates
                if(UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation)){
                    location = CGPointMake(location.y, location.x);
                }
            }

            if(!self.view.pointInside(self.view.convertPoint(location, fromView: self.view.window), withEvent: nil)){
                self.view.window?.removeGestureRecognizer(sender)
                self.dismissViewControllerAnimated(true, completion: nil)
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top