iOS: contrôleur de vue Modal avec fond transparent

j'essaie de présenter un contrôleur de vue modalement, avec un fond transparent. Mon but est de permettre à la fois la vue de Presentation et de presented view controllers d'être affichée en même temps. Le problème est que, lorsque l'animation de présentation se termine, la vue du contrôleur de vue de présentation disparaît.

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

je sais que je pourrais simplement ajouter la vue en tant que sous-vue, mais je voudrais éviter cette solution pour une raison ou une autre. Comment pourrais-je résoudre ce problème?

153
demandé sur Ajumal 2012-10-05 11:04:49

22 réponses

ce code suivant Ne fonctionne que sur l'iPad.

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

je dirais qu'il faut ajouter une sous-vue.

Voici une très bonne discussion. Regardez les commentaires, en particulier. Non seulement la réponse.

Modal Vue

Si j'étais vous, je ne le ferais pas. J'ajouterais une sous-vue et je le ferais. Il semble me donner un meilleur contrôle sur les choses.

EDIT:

comme mentionné par Paul Linsay, depuis iOS 8 Tout ce qui est nécessaire est UIModalPresentationOverFullScreen pour le modalPresentationStyle du ViewController étant présenté. Cela couvrirait également les boutons navigationBar et tabBar.

80
répondu S.P. 2017-10-12 20:21:04

pour ceux qui essayent de faire fonctionner ce contrôleur dans iOS 8, le moyen" approuvé par Apple "pour afficher un contrôleur de vue modal transparent est de mettre modalPresentationStyle sur le présent ed contrôleur à UIModalPresentationOverCurrentContext .

cela peut être fait en code, ou en définissant les propriétés de la séquence dans le storyboard.

De la UIViewController de la documentation:

Uimodeprésentationcourantcontexte

un style de présentation où le contenu est affiché sur seulement le contenu du contrôleur de vue parent. Les points de vue sous le présent le contenu ne sont pas retirés de la hiérarchie de vue lorsque la présentation terminer. Donc, si la vue-contrôleur ne remplit pas l'écran avec un contenu opaque, le contenu sous-jacent apparaît à travers.

lors de la présentation d'un contrôleur de vue dans un fenêtre pop-over, cette présentation le style est supporté seulement si le style de transition est Uimodaltransitionstylecovertical. Tenter d'utiliser un autre le style de transition déclenche une exception. Toutefois, vous pouvez utiliser d'autres styles de transition (sauf la transition de boucle partielle) si le parent - vue-contrôleur n'est pas dans une liste.

disponible à partir de iOS 8.0.

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

la vidéo' View Controller Advancements in iOS 8 ' de la WWDC 2014 va dans ce sens en détail.

Note:

  • assurez-vous de donner à votre contrôleur de vue présenté une couleur de fond claire, de peur qu'il ne soit pas réellement transparent!
  • vous devez définir ce avant présenter ie définir ce le paramètre dans le viewDidLoad du contrôleur presentedViewController n'aura pas d'effet
175
répondu Jeff C. 2017-10-12 19:34:37

Dans iOS 8.0 et au-dessus, il peut être fait par la définition de la propriété modalPresentationStyle à UIModalPresentationOverCurrentContext

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

88
répondu sat20786 2017-06-08 08:59:34

ce code fonctionne très bien sur iPhone sous iOS6 et iOS7:

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

dans ce cas, vous manquez l'animation de diapo. Pour conserver l'animation, vous pouvez toujours utiliser l'extension "non élégante" suivante:

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

si notre presentingV est situé à l'intérieur de UINavigationController ou UITabbarController vous devez opérer avec ces contrôleurs que presentingVC.

en outre, dans iOS7 vous pouvez mettre en œuvre la transition personnalisée animation appliquant le protocole UIViewControllerTransitioningDelegate . Bien sûr, dans ce cas, vous pouvez obtenir le fond transparent

@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>

D'abord, avant de présenter vous devez mettre modalPresentationStyle

modalViewController.modalPresentationStyle = UIModalPresentationCustom;

ensuite, vous devez mettre en œuvre deux méthodes de protocole

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

la dernière chose est de définir votre transition personnalisée dans CustomAnimatedTransitioning classe

@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
répondu malex 2014-08-19 22:06:30

créer une propriété de présentation de segue Pour présenter modalement et définir la propriété de présentation de cette segue à over current context il fonctionnera à 100%

enter image description here

15
répondu Venu Gopal Tewari 2015-01-21 18:38:32

j'ai eu un peu de mal avec le constructeur D'Interface de XCode 7 à définir le Style de présentation comme @VenuGopalTewari l'a suggéré. Dans cette version, il ne semble pas y avoir de mode de présentation Over Current Context ou Over Full Screen pour la suite. Ainsi, pour le faire fonctionner, j'ai réglé le mode à Default :

enter image description here avec enter image description here

en outre, j'ai mis la présentation mode du contrôleur de vue modalement présenté à Over Full Screen :

enter image description here

14
répondu Bastian 2015-10-14 10:26:24

PresentViewController avec un fond Transparent - dans iOS 8 et 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];

et dans MYViewController couleur de fond noir et réduire l'opacité

14
répondu Ashwini Chougale 2016-06-23 09:21:00

c'est un peu une façon de hacky, mais pour moi ce code fonctionne (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;

    }];
}];

ce code fonctionne aussi sur iPhone

12
répondu Mak 2013-09-24 11:29:40

cette catégorie a travaillé pour moi (ios 7, 8 et 9)

H fichier

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

M fichier

@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
répondu Ted 2015-10-14 06:36:39

j'ai ajouté ces trois lignes dans la méthode init dans le contrôleur de vue présenté, et fonctionne comme un charme:

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

MODIFIER (travail sur iOS 9.3):

self.modalPresentationStyle = UIModalPresentationOverFullScreen;

selon la documentation:

UIModalPresentationOverFullScreen Un style de présentation de vue dans lequel la vue présentée couvre l'écran. Les vues sous le contenu présenté ne sont pas retirés de la afficher la hiérarchie à la fin de la présentation. Ainsi, si le contrôleur de vue présenté ne remplit pas l'écran avec du contenu opaque, le contenu sous-jacent apparaît à travers.

disponible à partir de iOS 8.0.

6
répondu inigo333 2018-04-15 17:33:54

autre façon consiste à utiliser un "conteneur". Il suffit de faire alpha en dessous de 1 et d'intégrer avec séque. XCode 5, cible iOS7. Testé sur iPhone.

enter image description here

Conteneur affichage disponible à partir de iOS6. Lien post de blog à ce sujet.

4
répondu Mike Glukhov 2014-03-25 07:28:50

si vous utilisez Storyboard, vous pouvez suivre cette étape:

  1. Ajouter un contrôleur de vue (V2), configurer L'interface utilisateur comme vous le voulez
  • ajouter un fond uivi - set à noir et opacité à 0.5
  • ajouter un autre UIView (2) - qui servira de popup(les Pls prennent note que L'UIView et L'UIView (2) ne doivent pas avoir le même niveau/hiérarchie. Ne faites pas l' imageview l'enfant d'avis contraire de l'opacité de la uiview affectera la UIView(2))
  1. Présente V2 Modalement

  2. cliquez sur la suite. Dans les attributs inspecteur, définir la présentation comme sur le plein écran . Supprimer l'animation si vous aimez

Storyboard

  1. Sélectionnez V2. Dans les attributs inspecteur, définir la présentation comme sur le plein écran . Cochez définit le contexte et fournit le contexte

Storyboard

  1. sélectionnez la vue principale de votre V2 (Pls. Vérifier l'image). Réglez la couleur du fond sur couleur claire

Storyboard

4
répondu dhin 2017-09-20 03:24:06

j'ai créé un objet pour gérer la présentation de ce que j'appelle un" modal superposé", ce qui signifie qu'il conserve la vue de l'arrière-plan et vous permet d'avoir un modal avec un fond transparent.

il a une méthode simple et simple qui fait ceci:

- (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];
}

il est important de définir la propriété modalPresentationCapturesStatusBarAppearance à YES et de forcer l'apparence de la barre de statut à mettre à jour, si votre contrôleur de vue présenté a un différent preferredStatusBarStyle .

cet article devrait avoir un @property (assign, nonatommic) isPresenting

vous voulez que cet objet soit conforme aux protocoles UIViewControllerAnimatedTransitioning et UIViewControllerTransitioningDelegate et mettre en œuvre les méthodes suivantes:

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

    return self;
}

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

    return self;
}

et:

- (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];
        }];
    }
}

il s'agit d'une animation slide-in-from-the-bottom imitant l'animation modale par défaut, mais vous pouvez en faire ce que vous voulez.

l'important est que la vue du contrôleur de la vue de présentation restera à l'arrière, vous permettant de créer un effet transparent.

Cette solution fonctionne pour iOS 7+

3
répondu Pedro Mancheno 2015-10-13 20:57:47

une façon très simple de faire ceci (en utilisant Storyboards , par exemple) est:

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
}];

cela présentera un UIViewController dans un Storyboard modalement, mais avec un fond translucide.

3
répondu JaredH 2016-01-14 16:19:38

pour récapituler toutes les bonnes réponses et commentaires ici et d'avoir toujours une animation tout en se déplaçant à votre nouveau ViewController c'est ce que j'ai fait: (soutiens iOS 6 et plus)

Si votre utilisation d'un UINavigationController \ UITabBarController c'est le chemin à parcourir:

    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];

si vous le faites, vous perdrez votre animation modalTransitionStyle . Pour le résoudre, vous pouvez facilement ajouter à votre SomeViewController classe:

-(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
répondu Segev 2014-07-09 14:10:48

de Travail pour 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
répondu iluvatar_GR 2017-03-15 12:47:53

la solution à cette réponse en utilisant swift serait la suivante.

let vc = MyViewController()
vc.view.backgroundColor = UIColor.clear // or whatever color.
vc.modalPresentationStyle = .overCurrentContent
present(vc, animated: true, completion: nil)
2
répondu Anthony Dito 2017-07-06 16:21:39

si vous utilisez la séquence modale, assurez-vous de la définir comme cette image (vous pouvez désactiver l'animation si vous voulez) enter image description here

1
répondu Ahmed 2014-12-17 05:20:33

méthode complète Testée sur iOS 7 et iOS 8.

@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
répondu BB9z 2015-03-10 06:26:50

dans appdelegate :

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

dans votre contrôleur de première vue d'où vous devez charger la vue suivante:

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

    }];

dans votre nextViewController qui doit être ajouté transparent:

- (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
répondu Zaraki 2014-04-03 06:02:00

l'écran de connexion est un modal, c'est-à-dire qu'il se trouve au sommet de l'écran précédent. Jusqu'à présent, nous avons un arrière-plan flou, mais il n'est pas flou; c'est juste un arrière-plan gris.

nous devons régler notre Modal correctement.

lien de l'image cible

  • tout d'abord, nous devons changer l'arrière-plan de la vue du contrôleur pour effacer la couleur. Simplement signifie qu'il doit être transparent. Par défaut, ce point de Vue, il est blanc.

  • Deuxièmement, nous devons sélectionner la séquence qui mène à l'écran de connexion, et dans L'attribut Inspector, définir la présentation dans le contexte actuel. Cette option n'est disponible qu'avec mise en page automatique et Classes de taille activées.

lien de l'image cible

0
répondu tinkl 2015-04-15 07:05:50

Ensemble de la navigation modalPresentationStyle à UIModalPresentationCustom

et définissez la couleur d'arrière-plan de votre contrôleur de vue présenté comme une couleur claire.

0
répondu 2017-07-05 08:28:31