192 votes

iOS : ViewController modal avec arrière-plan transparent

J'essaie de présenter un contrôleur de vue de manière modale, avec un arrière-plan transparent. Mon objectif est de permettre à la vue du contrôleur de vue présentateur et du contrôleur de vue présenté 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 présenté 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 j'aimerais éviter cette solution pour une raison quelconque. Comment pourrais-je la corriger ?

10voto

dhin Points 432

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

  1. Ajoutez un contrôleur de vue (V2), configurez l'interface utilisateur comme vous le souhaitez.
  • ajouter un UIView - définir l'arrière-plan à noir et l'opacité à 0,5
  • ajouter un autre UIView(2) - qui servira de popup (Veuillez noter que l'UIView et l'UIView(2) doivent avoir le même niveau/hiérarchie. Ne faites pas de l'imageview l'enfant de la vue, sinon l'opacité de l'uiview affectera l'UIView(2)).
  1. Présenter V2 de manière modale

  2. Cliquez sur la transition. Dans l'inspecteur des attributs, définissez Présentation comme Sur le plein écran . Supprimez l'animation si vous le souhaitez

Storyboard

  1. Sélectionnez V2. Dans l'inspecteur des attributs, définissez Présentation comme Sur le plein écran . Vérifiez Définit le contexte et fournit le contexte

Storyboard

  1. Sélectionnez la vue principale de votre V2 (veuillez vérifier l'image). Définissez backgroundColor sur Couleur claire

Storyboard

7voto

inigo333 Points 181

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

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

EDIT (fonctionne sur iOS 9.3) :

self.modalPresentationStyle = UIModalPresentationOverFullScreen;

Selon la documentation :

UIModalPresentationOverFullScreen Un style de présentation de la vue dans lequel la vue présentée couvre l'écran. Les vues situées sous le contenu présenté ne sont pas supprimées de la hiérarchie des vues lorsque la présentation se termine. Ainsi, si le contrôleur de la vue présentée ne remplit pas l'écran avec un contenu opaque, le contenu sous-jacent est visible.

Disponible à partir de la version 8.0 d'iOS.

4voto

Mike Glukhov Points 49

Une autre solution consiste à utiliser une "vue conteneur". Il suffit de rendre l'alpha inférieur à 1 et de l'intégrer avec seque. XCode 5, cible iOS7. Testé sur iPhone.

enter image description here

Vue du conteneur disponible à partir d'iOS6. Lien à un article de blog à ce sujet.

4voto

pedro.m. Points 2743

J'ai créé un objet pour gérer la présentation de ce que j'appelle une "modale superposée", c'est-à-dire qu'il conserve la vue de l'arrière-plan et vous permet d'avoir une modale avec un arrière-plan transparent.

Il dispose d'une méthode unique et simple pour ce faire :

- (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 le modalPresentationCapturesStatusBarAppearance à la propriété YES et forcer la mise à jour de l'apparence de la barre d'état, si votre contrôleur de vue présenté a une autre preferredStatusBarStyle .

Cet objet doit avoir un @property (assign, nonatommic) isPresenting

Vous voulez que cet objet soit conforme à la 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 de type "slide-in-from-the-bottom" qui imite l'animation modale par défaut, mais vous pouvez en faire ce que vous voulez.

L'important, c'est que la vue du contrôleur de la vue de présentation reste à l'arrière, ce qui vous permet de créer un effet de transparence.

Cette solution fonctionne pour iOS 7+.

3voto

JaredH Points 1342

Une façon très simple de le faire (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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X