wake-up-neo.net

iOS: Modal ViewController mit transparentem Hintergrund

Ich versuche, einen View-Controller mit transparentem Hintergrund modal darzustellen. Mein Ziel ist es, die Ansicht der präsentierten und der präsentierten Ansichtssteuerung gleichzeitig anzeigen zu lassen. Das Problem ist, wenn die Präsentation der Präsentation beendet ist, verschwindet die Ansicht des Präsentationsansicht-Controllers.

- (IBAction)pushModalViewControllerButtonPressed:(id)sender
{
    ModalViewController *modalVC = [[ModalViewController alloc] init];
    [self presentViewController:modalVC animated:YES completion:nil];
}

Ich weiß, ich könnte die Ansicht einfach als Unteransicht hinzufügen, aber ich möchte diese Lösung aus irgendeinem Grund vermeiden. Wie könnte ich das beheben?

157
Michael

Dieser folgende Code funktioniert nur auf dem iPad.

self.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalVC animated:YES];

Ich würde eine Unteransicht hinzufügen. 

Hier ist eine sehr gute Diskussion. Schauen Sie sich die Kommentare genau an. Nicht nur die Antwort.

Modalansicht

Wenn ich du wäre, würde ich es nicht tun. Ich würde eine Unteransicht hinzufügen und es tun. Es scheint mir eine bessere Kontrolle über die Dinge zu geben.

EDIT: 

Wie von Paul Linsay erwähnt, ist seit iOS 8 alles, was benötigt wird, UIModalPresentationOverFullScreen für den modalPresentationStyle des ViewControllers. Dies würde auch die Schaltflächen navigationBar und tabBar umfassen.

82
S.P.

Für diejenigen, die versuchen, dies unter iOS 8 zu erreichen, besteht die "von Apple genehmigte" Methode zur Anzeige eines transparenten Modal View-Controllers darin, modalPresentationStyleauf dem aktuellen ed Controller auf UIModalPresentationOverCurrentContext zu setzen.

Dies kann im Code erfolgen oder durch Festlegen der Eigenschaften des Segments im Storyboard.

Aus der UIViewController-Dokumentation:

UIModalPresentationOverCurrentContext

Ein Präsentationsstil, bei dem der Inhalt nur über .__ angezeigt wird. Inhalt des übergeordneten View-Controllers. Die Ansichten unter der präsentierten Inhalt wird nicht aus der Ansichtshierarchie entfernt, wenn die Präsentation endet. Wenn also der dargestellte View-Controller den Bildschirm nicht ausfüllt mit undurchsichtigen Inhalten wird der zugrunde liegende Inhalt durchscheint.

Bei der Darstellung eines View-Controllers in einem Popover wird diese Präsentation style wird nur unterstützt, wenn der Übergangsstil .__ ist. UIModalTransitionStyleCoverVertical. Versuch, ein anderes .__ zu verwenden. Übergangsstil löst eine Ausnahme aus. Sie können jedoch auch andere .__ verwenden. Übergangsstile (mit Ausnahme des partiellen Curl-Übergangs), wenn das übergeordnete Element View Controller befindet sich nicht in einem Popover.

Verfügbar in iOS 8.0 und höher.

https://developer.Apple.com/documentation/uikit/uiviewcontroller

Das Video "View Controller Advancements in iOS 8" von der WWDC 2014 geht ausführlich darauf ein.

Hinweis:

  • Vergewissern Sie sich, dass Sie Ihrem präsentierten View-Controller eine klare Hintergrundfarbe geben, damit er nicht wirklich durchsichtig ist!
  • Sie müssen diese vorher -Darstellung setzen, dh das Setzen dieses Parameters in viewDidLoad des PresentationViewControllers hat keine Auswirkungen
179
Jeff C.

In iOS 8.0 und höher kann dies durch Setzen der Eigenschaft modalPresentationStyle auf UIModalPresentationOverCurrentContext erfolgen

//Set property **definesPresentationContext** YES to avoid presenting over presenting-viewController's navigation bar

self.definesPresentationContext = YES; //self is presenting view controller
presentedController.view.backgroundColor = [YOUR_COLOR with alpha OR clearColor]
presentedController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[self presentViewController:presentedController animated:YES completion:nil];

See Image Attached

89
sat20786

Dieser Code funktioniert auf dem iPhone unter iOS6 und iOS7 gut:

presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];

In diesem Fall verpassen Sie eine Slide-On-Animation. Um die Animation beizubehalten, können Sie noch die folgende "nicht elegante" Erweiterung verwenden:

[presentingVC presentViewController:presentedVC animated:YES completion:^{
    [presentedVC dismissViewControllerAnimated:NO completion:^{
        presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
        [presentingVC presentViewController:presentedVC animated:NO completion:NULL];
    }];
}];

Wenn sich unser PresentingV im UINavigationController oder UITabbarController befindet, müssen Sie diese Controller als PresentingVC verwenden.

In iOS7 können Sie außerdem eine benutzerdefinierte Übergangsanimation mithilfe des UIViewControllerTransitioningDelegate-Protokolls implementieren. In diesem Fall können Sie natürlich einen transparenten Hintergrund erhalten

@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>

Bevor Sie präsentieren, müssen Sie modalPresentationStyle einstellen.

modalViewController.modalPresentationStyle = UIModalPresentationCustom;

Dann müssen Sie zwei Protokollmethoden implementieren

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    CustomAnimatedTransitioning *transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = YES;
    return transitioning;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    CustomAnimatedTransitioning * transitioning = [CustomAnimatedTransitioning new];
    transitioning.presenting = NO;
    return transitioning;
}

Als letztes müssen Sie Ihren benutzerdefinierten Übergang in der Klasse CustomAnimatedTransitioning definieren

@interface CustomAnimatedTransitioning : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end

@implementation CurrentContextTransitionAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    return 0.25;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    if (self.presenting) {
        // custom presenting animation
    }
    else {
        // custom dismissing animation
    }
}
42
malex

Ich habe ein wenig mit dem Interface Builder von XCode 7 gekämpft, um den Präsentationsstil als @VenuGopalTewari vorgeschlagen zu setzen. In dieser Version scheint es keinen Over Current Context- oder Over Full Screen-Präsentationsmodus für das Segment zu geben. Damit das funktioniert, setze ich den Modus auf Default:

 enter image description here mit  enter image description here

Zusätzlich habe ich den Präsentationsmodus des modal dargestellten View-Controllers auf Over Full Screen eingestellt:

 enter image description here

17
Bastian

Erstellen Sie ein Segment, um es modal darzustellen, und legen Sie die Presentation-Eigenschaft dieses Segments auf den aktuellen Kontext festIt funktioniert 100%.

enter image description here

16

PresentViewController mit transparentem Hintergrund - in iOS 8 und iOS 9

MYViewController *myVC = [self.storyboard   instantiateViewControllerWithIdentifier:@"MYViewController"];
    myVC.providesPresentationContextTransitionStyle = YES;
    myVC.definesPresentationContext = YES;
    [myVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    [self.navigationController presentViewController:myVC animated:YES completion:nil];

Und in MYViewController die Hintergrundfarbe schwarz einstellen und die Deckkraft verringern 

14

Es ist ein bisschen gehackt, aber für mich funktioniert dieser Code (iOS 6): 

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

[self presentViewController:self.signInViewController animated:YES completion:^{
    [self.signInViewController dismissViewControllerAnimated:NO completion:^{
        appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
        [self presentViewController:self.signInViewController animated:NO completion:nil];
        appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;

    }];
}];

Dieser Code funktioniert auch auf dem iPhone

12
Mak

Diese Kategorie arbeitete für mich (iOS 7, 8 und 9)

H-Datei

@interface UIViewController (navigation)
- (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end

M-Datei

@implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
    if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
        [self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];

    }else{
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
         [self presentViewController:viewControllerToPresent animated:YES completion:completion];
    }
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
    UIViewController *presentingVC = self;
    UIViewController *root = self;
    while (root.parentViewController) {
        root = root.parentViewController;
    }
    UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
    root.modalPresentationStyle = UIModalPresentationCurrentContext;
    [presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
        root.modalPresentationStyle = orginalStyle;
    }];
}
@end
11
Ted

Wenn Sie das Storyboard verwenden, können Sie diesen Schritt ausführen:

  1. Fügen Sie einen View Controller (V2) hinzu, und richten Sie die Benutzeroberfläche wie gewünscht ein
  • fügen Sie einen UIView - Hintergrund für Schwarz und Deckkraft für 0,5 hinzu
  • fügen Sie eine weitere UIView (2) hinzu - die als Popup dient (Pls beachten, dass UIView und UIView (2) dieselbe Ebene/Hierarchie haben müssen. Machen Sie die Image-Ansicht nicht zum Kind der Ansicht, andernfalls wird die Deckkraft der Uiview verwendet Auswirkungen auf die UIView (2))
  1. V2 modal präsentieren

  2. Klicken Sie auf das Segue. Legen Sie im Eigenschafteninspektor die Option Präsentation als Über Vollbild fest. Entfernen Sie die Animation, wenn Sie möchten

Storyboard

  1. Wählen Sie V2 aus. Legen Sie im Eigenschafteninspektor die Option Präsentation als Über Vollbild fest. Check Definiert den Kontext und stellt den Kontext bereit

Storyboard

  1. Wählen Sie die Hauptansicht Ihrer V2 (Bitte überprüfen Sie das Bild). Setze backgroundColor auf Farbe löschen

Storyboard

6
dhin

Ich habe diese drei Zeilen in der init-Methode im vorgestellten View-Controller hinzugefügt und funktioniert wie ein Zauber:

self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[self setModalPresentationStyle:UIModalPresentationOverCurrentContext];

BEARBEITEN (arbeitet an iOS 9.3):

self.modalPresentationStyle = UIModalPresentationOverFullScreen;

Wie in der Dokumentation:

UIModalPresentationOverFullScreen Ein Darstellungsstil der Ansicht, in dem die dargestellte Ansicht den Bildschirm abdeckt. Die Ansichten unter dem präsentierten Inhalt werden nach Abschluss der Präsentation nicht aus der Ansichtshierarchie entfernt. Wenn also der dargestellte View-Controller den Bildschirm nicht mit undurchsichtigen Inhalten füllt, wird der zugrunde liegende Inhalt sichtbar.

Verfügbar in iOS 8.0 und höher.

6
inigo333

Alternativ können Sie eine "Containeransicht" verwenden. Einfach Alpha unter 1 machen und mit Seque einbetten. XCode 5, Ziel iOS7. Auf dem iPhone getestet.

enter image description here

Containeransicht verfügbar unter iOS6 . Link zum Blogbeitrag darüber.

4
Mike Glukhov

Die Lösung für diese Antwort mit Swift wäre wie folgt.

let vc = MyViewController()
vc.view.backgroundColor = UIColor.clear // or whatever color.
vc.modalPresentationStyle = .overCurrentContent
present(vc, animated: true, completion: nil)
3
Anthony Dito

Ich habe ein Objekt erstellt, das die Darstellung eines "überlagerten Modals" behandelt, das heißt, es behält die Ansicht des Hintergrunds bei und ermöglicht Ihnen, einen Modal mit transparentem Hintergrund zu haben.

Es gibt eine einfache Methode, die dies ausführt:

- (void)presentViewController:(UIViewController *)presentedViewController
       fromViewController:(UIViewController *)presentingViewController
{
    presentedViewController.modalPresentationStyle = UIModalPresentationCustom;
    presentedViewController.transitioningDelegate = self;
    presentedViewController.modalPresentationCapturesStatusBarAppearance = YES;

    [presentedViewController setNeedsStatusBarAppearanceUpdate];

    [presentingViewController presentViewController:presentedViewController
                                       animated:YES
                                     completion:nil];
}

Es ist wichtig, die modalPresentationCapturesStatusBarAppearance-Eigenschaft auf YES zu setzen und die Aktualisierung der Statusleiste zu erzwingen, wenn Ihr präsentierter View-Controller eine andere preferredStatusBarStyle hat.

Dieses Objekt sollte eine @property (assign, nonatommic) isPresenting haben

Sie möchten, dass dieses Objekt den Protokollen UIViewControllerAnimatedTransitioning und UIViewControllerTransitioningDelegate entspricht und die folgenden Methoden implementiert:

- (id)animationControllerForPresentedController:(UIViewController *)presented
                           presentingController:(UIViewController *)presenting
                               sourceController:(UIViewController *)source
{
    self.isPresenting = YES;

    return self;
}

- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
    self.isPresenting = NO;

    return self;
}

und:

- (NSTimeInterval)transitionDuration:(id)transitionContext
{
    return 0.25;
}

- (void)animateTransition:(id)transitionContext
{
    UIViewController* firstVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController* secondVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView* containerView = [transitionContext containerView];
    UIView* firstView = firstVC.view;
    UIView* secondView = secondVC.view;

    if (self.isPresenting) {
        [containerView addSubview:secondView];
        secondView.frame = (CGRect){
            containerView.frame.Origin.x,
            containerView.frame.Origin.y + containerView.frame.size.height,
            containerView.frame.size
        };

        firstView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
        [UIView animateWithDuration:0.25 animations:^{
            secondView.frame = containerView.frame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
        } else {
        [UIView animateWithDuration:0.25 animations:^{
            firstView.frame = (CGRect){
                containerView.frame.Origin.x,
                containerView.frame.Origin.y + containerView.frame.size.height,
                containerView.frame.size
        };

        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
}

Dabei wird eine Animation von der Unterseite nach unten der Standard-Modal-Animation nachgebildet. Sie können sie jedoch beliebig gestalten.

Wichtig ist, dass die Ansicht des Presenting View Controllers hinten bleibt, sodass Sie einen transparenten Effekt erzeugen können.

Diese Lösung funktioniert für iOS 7+

3
Pedro Mancheno

Eine sehr einfache Möglichkeit, dies zu tun (beispielsweise mit Storyboards), ist:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"SomeStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SomeStoryboardViewController"];
// the key for what you're looking to do:
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
vc.view.alpha = 0.50f;

[self presentViewController:vc animated:YES completion:^{
    // great success
}];

Dadurch wird eine UIViewController in einer Storyboard modal dargestellt, jedoch mit einem durchscheinenden Hintergrund.

3
JaredH

Arbeiten für iOS 7-10

if #available(iOS 8.0, *) {
    nextVC.modalPresentationStyle = .OverCurrentContext
    self.presentViewController(nextVC, animated: true, completion: nil)
} else {
    // Fallback on earlier version
    self.modalPresentationStyle = .Custom          
    nextVC.modalTransitionStyle = .CrossDissolve            
    self.presentViewController(nextVC, animated: false, completion: nil)
    }
}
2
iluvatar_GR

Um alle guten Antworten und Kommentare hier zusammenzufassen und trotzdem eine Animation zu haben, während Sie zu Ihrer neuen ViewController wechseln, habe ich Folgendes getan: (Unterstützt iOS 6 und höher)

Wenn Sie eine UINavigationController\UITabBarController verwenden, gehen Sie wie folgt vor:

    SomeViewController *vcThatWillBeDisplayed = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeVC"];

    vcThatWillBeDisplayed.view.backgroundColor = [UIColor colorWithRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:0.50];    

    self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:presentedVC animated:YES completion:NULL];

Wenn Sie das tun, verlieren Sie Ihre modalTransitionStyle-Animation. Um dies zu lösen, können Sie Ihrer SomeViewController-Klasse Folgendes hinzufügen:

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIView animateWithDuration:0.4 animations:^() {self.view.alpha = 1;}
       completion:^(BOOL finished){}];
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.alpha = 0;
}
2
Segev

Swift 4.2

guard let someVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someVC") as? someVC else {
    return
}
someVC.modalPresentationStyle = .overCurrentContext

present(someVC, animated: true, completion: nil)
1

Wenn Sie modales Segue verwenden, stellen Sie sicher, dass es als dieses Bild festgelegt ist (Sie können die Animation deaktivieren, wenn Sie möchten)enter image description here

1
Ahmed

Natürlich sollten Sie UIModalPresentationCurrentContext einstellen, aber clearColor ist auch sehr wichtig! Sie können den Hintergrund in der viewDidLoad-Funktion nicht festlegen. Setzen Sie ihn vor dem Laden der Ansicht wie in root view controller oder in der init-Funktion des Controllers, der angezeigt wird!

actionController.view.backgroundColor = [UIColor clearColor];
[self presentViewController:actionController animated:YES completion:nil];

oder

- (instancetype)init {

    self = [super initWithNibName:nil bundle:nil];

    if(self) {
        self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
        [self.view setBackgroundColor:[UIColor clearColor]];
    }

    return self;
}
1
Santiago

Eine vollständige Methode, die auf iOS 7 und iOS 8 getestet wurde.

@interface UIViewController (MBOverCurrentContextModalPresenting)

/// @warning Some method of viewControllerToPresent will called twice before iOS 8, e.g. viewWillAppear:.
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;

@end

@implementation UIViewController (MBOverCurrentContextModalPresenting)

- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
    UIViewController *presentingVC = self;

    // iOS 8 before
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
        UIViewController *root = presentingVC;
        while (root.parentViewController) {
            root = root.parentViewController;
        }

        [presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
            [viewControllerToPresent dismissViewControllerAnimated:NO completion:^{
                UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
                if (orginalStyle != UIModalPresentationCurrentContext) {
                    root.modalPresentationStyle = UIModalPresentationCurrentContext;
                }
                [presentingVC presentViewController:viewControllerToPresent animated:NO completion:completion];
                if (orginalStyle != UIModalPresentationCurrentContext) {
                    root.modalPresentationStyle = orginalStyle;
                }
            }];
        }];
        return;
    }

    UIModalPresentationStyle orginalStyle = viewControllerToPresent.modalPresentationStyle;
    if (orginalStyle != UIModalPresentationOverCurrentContext) {
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    }
    [presentingVC presentViewController:viewControllerToPresent animated:YES completion:completion];
    if (orginalStyle != UIModalPresentationOverCurrentContext) {
        viewControllerToPresent.modalPresentationStyle = orginalStyle;
    }
}

@end
1
BB9z

Setze modalPresentationStyle der Navigation auf UIModalPresentationCustom

und legen Sie die Hintergrundfarbe Ihres präsentierten View-Controllers als klare Farbe fest.

0
user3693546

in appdelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[_window rootViewController]setModalPresentationStyle:UIModalPresentationCurrentContext];
    return YES;
}

in Ihrer ersten Ansicht Controller, von wo aus Sie die nächste Ansicht laden müssen:

  NextViewController *customvc = [[NextViewController alloc]init];
    [self presentViewController:customvc animated:YES completion:^{

    }];

in Ihrem nextViewController der transparent hinzugefügt werden soll:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor clearColor];
    UIView* backView = [[UIView alloc] initWithFrame:self.view.frame];
    backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
    [self.view insertSubview:backView atIndex:0];
}
0
Zaraki

Der Anmeldebildschirm ist modal, dh er befindet sich oben auf dem vorherigen Bildschirm. Bisher haben wir unscharfen Hintergrund, aber es verwischt nichts. es ist nur ein grauer Hintergrund.

Wir müssen unseren Modal richtig einstellen.

image link target

  • Zuerst müssen wir den Ansichtshintergrund des View Controllers in Farbe löschen ändern. Es bedeutet einfach, dass es transparent sein sollte. Diese Ansicht ist standardmäßig weiß.

  • Zweitens müssen Sie den Segue auswählen, der zum Anmeldebildschirm führt, und im Attributinspektor die Darstellung auf Over Current Context setzen. Diese Option ist nur verfügbar, wenn Auto-Layout und Größenklassen aktiviert sind.

image link target

0
tinkl