Afficher clearColor UIViewController sur UIViewController

150

j'ai un UIViewController vue sous-vue / modale sur une autreUIViewController vue, telle que la sous-vue / modale doit être transparente et tous les composants ajoutés à la sous-vue doivent être visibles. Le problème est que la sous-vue montre un fond noir à la place pour avoir clearColor. J'essaie de faire UIViewun fond clair et non noir. Quelqu'un sait-il ce qui ne va pas? Toute suggestion appréciée.

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];

[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentModalViewController:vc animated:NO];  

SecondViewController.m

- (void)viewDidLoad 
{
     [super viewDidLoad];
     self.view.opaque = YES;
     self.view.backgroundColor = [UIColor clearColor];
}

RÉSOLU : j'ai résolu les problèmes. Cela fonctionne si bien pour iPhone et iPad. Modal View Controller sans fond noir juste clearColor / transparent. La seule chose que j'ai besoin de changer est que j'ai remplacéUIModalPresentationFullScreen parUIModalPresentationCurrentContext . Comme c'est simple!

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];

AVIS: si vous utilisez unmodalPresentationStyle propriété de navigationController:

FirstViewController.m

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];

AVIS: La mauvaise nouvelle est que la solution ci-dessus ne fonctionne pas sur iOS 7. La bonne nouvelle est que j'ai résolu le problème pour iOS7! J'ai demandé de l'aide à quelqu'un et voici ce qu'il a dit:

Lors de la présentation modale d'un contrôleur de vue, iOS supprime les contrôleurs de vue situés en dessous de la hiérarchie de vues pendant la durée de sa présentation. Alors que la vue de votre contrôleur de vue présenté modalement est transparente, il n'y a rien en dessous sauf la fenêtre de l'application, qui est noire. iOS 7 a introduit un nouveau style de présentation modal UIModalPresentationCustom, qui empêche iOS de supprimer les vues sous le contrôleur de vue présenté. Cependant, pour utiliser ce style de présentation modale, vous devez fournir votre propre délégué de transition pour gérer la présentation et ignorer les animations. Ceci est décrit dans la présentation «Transitions personnalisées à l'aide de contrôleurs de vue» de WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218 qui explique également comment implémenter votre propre délégué de transition.

Vous pouvez voir ma solution pour le problème ci-dessus dans iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

haute technologie
la source
1
assurez-vous de définir le modalPresentationStyle du rootViewController, sinon cela ne fonctionnera pas
Thorsten
Veuillez jeter un oeil au commentaire sur cette réponse stackoverflow.com/a/25990081/1418457 , ça marche
onmyway133
Ce stackoverflow.com/q/27598846/1603234 me fait sourire, maintenant à votre tour :)
Hemang
J'ai dû faire self.modalPresentationStyle = UIModalPresentationCurrentContext; avec le contrôleur de vue présenté pour le faire fonctionner, pas avec celui de présentation.
Tulleb
1
Vérifiez la réponse de Brody ci-dessous. modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; résoudra le problème,
GoodSp33d

Réponses:

143

iOS8 +

Dans iOS8 +, vous pouvez désormais utiliser le nouveau modalPresentationStyle UIModalPresentationOverCurrentContext pour présenter un contrôleur de vue avec un arrière-plan transparent:

MyModalViewController *modalViewController = [[MyModalViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;           
[self presentViewController:modalViewController animated:YES completion:nil];    
Brody Robertson
la source
5
Devrait être la réponse acceptée. La réponse précédemment acceptée est toujours valide pour des raisons héritées, mais c'est la méthode recommandée.
Tomasz Bąk
3
Si vous développez uniquement pour iOS 8, optez pour cette réponse! Ça marche
Mário Carvalho
2
C'est bien, mais la dernière ligne ne devrait-elle pas l'être [self presentViewController:modalViewController animated:YES completion:nil];? (au lieu de targetController)?
SuperDuperTango
3
Afin de travailler cela pour moi, j'ai ajouté modalViewController.view.backgroundColor = UIColor.clearColor () merci pour la solution
Pramod
Quelqu'un peut-il me fournir le code pour pushviewcontroller aussi (je veux dire pour le contrôleur de navigation).
Alok
140

RÉSOLU : j'ai résolu les problèmes. Cela fonctionne si bien pour iPhone et iPad. Modal View Controller sans fond noir juste clearColor / transparent. La seule chose que je dois changer est que j'ai remplacé UIModalPresentationFullScreen par UIModalPresentationCurrentContext. Comme c'est simple!

FirstViewController.m

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    vc.view.backgroundColor = [UIColor clearColor];
    self.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:vc animated:NO completion:nil];

AVIS: Si vous utilisez une propriété modalPresentationStyle de navigationController:

FirstViewController.m

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    vc.view.backgroundColor = [UIColor clearColor];
    self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentViewController:vc animated:NO completion:nil];

AVIS: La mauvaise nouvelle est que la solution ci-dessus ne fonctionne pas sur iOS 7. La bonne nouvelle est que j'ai résolu le problème pour iOS7! J'ai demandé de l'aide à quelqu'un et voici ce qu'il a dit:

Lors de la présentation modale d'un contrôleur de vue, iOS supprime les contrôleurs de vue situés en dessous de la hiérarchie de vues pendant la durée de sa présentation. Alors que la vue de votre contrôleur de vue présenté modalement est transparente, il n'y a rien en dessous sauf la fenêtre de l'application, qui est noire. iOS 7 a introduit un nouveau style de présentation modal, UIModalPresentationCustom, qui empêche iOS de supprimer les vues sous le contrôleur de vue présenté. Cependant, pour utiliser ce style de présentation modale, vous devez fournir votre propre délégué de transition pour gérer la présentation et ignorer les animations. Ceci est décrit dans la présentation «Transitions personnalisées à l'aide de contrôleurs de vue» de WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218 qui explique également comment implémenter votre propre délégué de transition.

Vous pouvez voir ma solution pour le problème ci-dessus dans iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

haute technologie
la source
1
self.modalPresentationStyle = UIModalPresentationCurrentContext;l'a fait.
Adriano Lucas
4
btw .. J'ai observé cela à cause de self.modalPresentationStyle = UIModalPresentationCurrentContext; il ne présente pas modalViewController avec une animation .. des idées?
Devarshi
1
@Miraaj Ensuite, redéfinir modalPresentationStyle sur UIModalPresentationFullScreen avant d'afficher UIViewController devrait fonctionnerself.modalPresentationStyle = UIModalPresentationFullScreen; [self performSegueWithIdentifier:@"CustomSegue" sender:self];
hightech
1
En exécutant cela dans iOS 6 et 7, le nouveau contrôleur de vue est clair lors de l'animation de la présentation, mais une fois qu'il est en place, l'arrière-plan devient noir. Cela redevient clair lors de l'animation du renvoi. Quelqu'un d'autre a-t-il eu ce problème?
Drew C
3
@pkamb J'ai mis à jour la solution pour iOS 7. stackoverflow.com/a/11252969/1344459 J'espère que cela vous aidera.
hightech
114

Donc, pour les penseurs purement visuels et les fans de storyboard, vous pouvez faire:

1. Présentation de View Controller

Définir le contexte

2. Contrôleur de vue présenté

Présentation: sur le contexte actuel

pasevin
la source
Cela devrait être la réponse acceptée. C'est tout ce que vous avez à faire pour que cela fonctionne, puis définissez la couleur d'arrière-plan de la vue sur le contrôleur modal sur effacer.
Jesse le
D'accord, les options de storyboard écrasent le code dans ce cas.
C0D3
17
Cette réponse est si douce, j'ai maintenant le diabète.
GeneCode
25

Solution Swift 3 et iOS10:

//create view controller
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "RoadTripPreviewViewController")
//remove black screen in background
vc.modalPresentationStyle = .overCurrentContext
//add clear color background
vc.view.backgroundColor = UIColor.clear
//present modal
self.present(vc, animated: true, completion: nil)
Kevin ABRIOUX
la source
16

Ceci provient de xCode 7 beta 4 en utilisant une séquence de glissement de contrôle. Définissez simplement l'arrière-plan de votre destination pour effacer et définissez les propriétés de segue dans IB comme suit (nb. La présentation peut également être "En plein écran"):

entrez la description de l'image ici

smileBot
la source
2
MERCI. J'ai fait votre correction de segue + la réponse de ViewControllers par @pasevin et cela a fonctionné !!
CSawy
1
Cela a répondu à ma question. Merci beaucoup. Avoir un vote pour: D
Nate4436271
8

J'ai trouvé le moyen le plus simple de le faire fonctionner sur iOS7 et iOS8 est d'ajouter set the presentationStyle à UIModalPresentationOverCurrentContext sur le modallyPresentedVC (ViewController que vous souhaitez présenter de manière modale) à cause d'iOS8:

[modallyPresentedVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[modallyPresentedVC.navigationController setModalPresentationStyle:UIModalPresentationOverCurrentContext];

et UIModalPresentationCurrentContext sur presentationVC (le contrôleur qui présente le modallyPresented) à cause d'iOS7:

[presentingVC setModalPresentationStyle:UIModalPresentationCurrentContext];
[presentingVC.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext];

Parce que les choses sont gérées différemment sur iOS7 et iOS8. Bien sûr, vous n'avez pas besoin de définir les propriétés navigationController si vous n'en utilisez pas. J'espère que cela pourra aider.

3vangelos
la source
sauvé mon bacon! Merci
Duck
5

Version Swift2:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewController") as! YourViewController
vc.view.backgroundColor = UIColor.clearColor()
vc.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen // orOverCurrentContext to place under navigation
self.presentViewController(vc, animated: true, completion: nil)
Mojtabye
la source
4

Une autre façon (pas besoin de créer une transition personnalisée et fonctionne sur iOS 7)

Utilisation de Storyboard:

Créez le contrôleur de vue enfant avec une taille de liberté, définissez la largeur de la vue sur 500x500 (par exemple) et ajoutez la méthode suivante:

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
    self.view.superview.bounds = CGRectMake(0, 0, 500, 500);
    self.view.superview.backgroundColor = [UIColor clearColor];
}

Ensuite, créez une séquence modale avec feuille de formulaire et testez-la.

EducaPix
la source
Vous êtes incroyable!!! cela fonctionne réellement !!! (définir la taille "liberté" dans IB n'affecte pas anithing car c'est une métrique simulée, mais de toute façon, ça marche !!!) et c'est tellement simple !!!
Radu Simionescu
4

Solution iOS 7 avec segue personnalisé:

CustomSegue.h
#import <UIKit/UIKit.h>

    @interface CustomSegue : UIStoryboardSegue <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>

    @end



CustomSegue.m
#import "CustomSegue.h"

@implementation CustomSegue

-(void)perform {

    UIViewController* destViewController = (UIViewController*)[self destinationViewController];
    destViewController.view.backgroundColor = [UIColor clearColor];
    [destViewController setTransitioningDelegate:self];
    destViewController.modalPresentationStyle = UIModalPresentationCustom;
    [[self sourceViewController] presentViewController:[self destinationViewController] animated:YES completion:nil];
}


//===================================================================
// - UIViewControllerAnimatedTransitioning
//===================================================================

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

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {

    UIView *inView = [transitionContext containerView];
    UIViewController* toVC = (UIViewController*)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromVC = (UIViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [inView addSubview:toVC.view];

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    [toVC.view setFrame:CGRectMake(0, screenRect.size.height, fromVC.view.frame.size.width, fromVC.view.frame.size.height)];

    [UIView animateWithDuration:0.25f
                     animations:^{

                         [toVC.view setFrame:CGRectMake(0, 0, fromVC.view.frame.size.width, fromVC.view.frame.size.height)];
                     }
                     completion:^(BOOL finished) {
                         [transitionContext completeTransition:YES];
                     }];
}


//===================================================================
// - UIViewControllerTransitioningDelegate
//===================================================================

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {

    return self;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    //I will fix it later.
    //    AnimatedTransitioning *controller = [[AnimatedTransitioning alloc]init];
    //    controller.isPresenting = NO;
    //    return controller;
    return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator {
    return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {
    return nil;
}

@end

Solution basée sur un code de haute technologie.

Max Gribov
la source
Quand je ferme le by [self licenciementViewControllerAnimated: OUI achèvement: NULL]; Je reçois une exception ??
Asadullah Ali
Oui pour ce code. Ou vous devez implémenter la méthode animationControllerForDismissedController pour que l'animation commence le travail.
Max Gribov
4

Pour moi, cela fonctionne:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"MMPushNotificationViewController"];

    vc.view.backgroundColor = [UIColor clearColor];
    self.modalPresentationStyle = UIModalPresentationCurrentContext;
#ifdef __IPHONE_8_0
    if(IS_OS_8_OR_LATER)
    {
        self.providesPresentationContextTransitionStyle = YES;
        self.definesPresentationContext = YES;
        [vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    }
#endif


    [self presentViewController:vc animated:NO completion:nil];

MMPushNotificationViewControllerest le contrôleur de la vue transparente et j'ai également rendu la MMPushNotificationViewControllercouleur de la vue de la couleur claire. Maintenant tout ce que j'ai fait et fait mon Transparentviewcontroller.

Manab Kumar Mal
la source
2

Pour iOS7

Il existe maintenant un moyen d'y parvenir en utilisant les transitions personnalisées iOS7, de cette façon:

MyController * controller = [MyController new];
[controller setTransitioningDelegate:self.transitionController];
controller.modalPresentationStyle = UIModalPresentationCustom;
[self controller animated:YES completion:nil];

Pour créer votre transition personnalisée, vous avez besoin de 2 choses:

  • Un objet TransitionDelegate (implémentation <UIViewControllerTransitionDelegate> )
  • Un objet "AnimatedTransitioning" (implémentation <UIViewControllerAnimatedTransitioning>)

Vous pouvez trouver plus d'informations sur les transitions personnalisées dans ce tutoriel .

Kirualex
la source
Des raisons spécifiques pour lesquelles vous avez ajouté mainviewcontroller et deuxième classe de contrôleur de vue dans la classe animator? pourquoi n'avez-vous pas utilisé directement UIViewController * toVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextFromViewControllerKey];
Satyam Raikar
Ce n'est pas mon tutoriel donc je ne connais pas les tenants et aboutissants à ce sujet. Votre point semble cependant valable.
Kirualex
2

Fonctionne très bien sur iOS7 et iOS8

UIViewController* vc=[[UIViewController alloc]initWithNibName:@"VC" bundle:nil];

vc.view.alpha=0.7;
[vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];

self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;

[self presentViewController:vc animated:NO completion:nil];
houblon
la source
Un double de la deuxième meilleure réponse.
Tomasz Bąk
2

Vous pouvez également «rajouter» la fenêtre à la vue.

OneViewController *vc = [[OneViewController alloc] init];
if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
    [self presentViewController:vc animated:YES completion:nil];
} else {
    [self presentModalViewController:vc animated:YES];
}

[[[UIApplication sharedApplication] keyWindow] insertSubview:self.view atIndex:0];

Et de cette manière, la présentation peut être animée.

Sundae elfe
la source
1

Pour iOS 7 et uniquement en utilisant Interface Builder, cela peut être accompli en définissant la présentation sur «Over Current Context» sur tous les contrôleurs de vue impliqués dans la présentation modale. Même pour les contrôleurs de navigation.

Par exemple, définissez-le sur tous ces contrôleurs de vue:

NavController -> RootViewController -> ModalViewController

entrez la description de l'image ici

David Hernandez
la source
0

Je n'ai pas beaucoup joué avec le constructeur de Storyboard / Interface, mais ce qui me ressort, c'est que vous dites que la vue est de couleur claire (c'est-à-dire 100% alpha / transparent) et que vous lui dites également qu'elle est opaque ( 0% alpha - complètement solide). Ces deux choses ne semblent pas concorder. Je commenterais la self.view.opaque = YES;ligne et voir si cela fonctionne alors;)

Ah, autre chose à laquelle je viens de penser - il est tout à fait possible que votre contrôleur de vue ait l'arrière-plan alpha, mais bien sûr, l'alpha sera affiché jusqu'à la couleur de la fenêtre de base ou du contrôleur de vue racine du programme, ce qui est par noir par défaut. La couche de base de toute votre application ne peut pas avoir un arrière-plan transparent - transparent à quoi? Qu'y a-t-il derrière? Il doit y avoir quelque chose à voir A TRAVERS la transparence. Cela a-t-il du sens?

WendiKidd
la source
J'ai essayé de commenter le self.view.opaque = YES; ligne et cela ne fonctionne pas. :-(
hightech
Avez-vous lu la deuxième partie de ma réponse? Vous ne pourrez peut-être pas faire ce que vous voulez, selon votre configuration. Que placez-vous derrière le clearColor VC? Peut-être que nous pouvons régler cela ^^
WendiKidd
-3

Utilisez simplement "self.modalPresentationStyle = UIModalPresentationCurrentContext;", dans la vue de présentation

Fonctionnera très bien :)

Venkateswarlu.NP
la source
1
C'est juste répéter ce que les réponses existantes ont déjà dit.
Pang