Vue modale transparente sur le contrôleur de navigation

J’essaie de créer une vue modale transparente sur mon contrôleur de navigation. Est-ce que quelqu’un sait si c’est possible?

Une vue modale couvrira la vue sur laquelle elle est placée ainsi que la barre de navigation de votre contrôleur de navigation. Cependant, si vous utilisez l’option -presentModalViewController: animated: approach, une fois l’animation terminée, la vue que vous venez de parcourir disparaîtra, ce qui rend inutile toute transparence de votre vue modale. (Vous pouvez le vérifier en implémentant les méthodes -viewWillDisappear: et -viewDidDisappear: dans votre contrôleur de vue racine).

Vous pouvez append la vue modale directement à la hiérarchie de la vue comme suit:

UIView *modalView = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; modalView.opaque = NO; modalView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f]; UILabel *label = [[[UILabel alloc] init] autorelease]; label.text = @"Modal View"; label.textColor = [UIColor whiteColor]; label.backgroundColor = [UIColor clearColor]; label.opaque = NO; [label sizeToFit]; [label setCenter:CGPointMake(modalView.frame.size.width / 2, modalView.frame.size.height / 2)]; [modalView addSubview:label]; [self.view addSubview:modalView]; 

L’ajout de modalView en tant que sous-vue à la vue racine ne couvre pas réellement la barre de navigation, mais couvre l’intégralité de la vue en dessous. J’ai essayé de jouer avec l’origine du cadre utilisé pour lancer modalView, mais les valeurs négatives l’empêchent de s’afficher. La meilleure méthode que j’ai trouvée pour couvrir tout l’écran en plus de la barre d’état est d’append le modalView en tant que sous-vue de la fenêtre elle-même:

 TransparentModalViewAppDelegate *delegate = (TransparentModalViewAppDelegate *)[UIApplication sharedApplication].delegate; [delegate.window addSubview:modalView]; 

Le moyen le plus simple consiste à utiliser la propriété modalPresentationStyle de navigationController (mais vous devrez créer une animation par vous-même):

 self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; [self presentModalViewController:modalViewController animated:NO]; modalViewController.view.alpha = 0; [UIView animateWithDuration:0.5 animations:^{ modalViewController.view.alpha = 1; }]; 

Je le fais très facilement en configurant un “OverlayViewController” qui se trouve au-dessus de toutes les sous-vues de ma fenêtre ou de ma vue racine. Configurez cette option dans votre contrôleur d’application ou votre contrôleur d’affichage racine et faites de OverlayViewController un singleton pour qu’il soit accessible de n’importe où dans votre code ou dans la hiérarchie de contrôleurs. Vous pouvez ensuite appeler des méthodes pour afficher les vues modales, afficher des indicateurs d’activité, etc., à tout moment, et elles peuvent potentiellement couvrir tous les tabs ou contrôleurs de navigation.

Exemple de code pour le contrôleur de vue racine:

 - (void)viewDidLoad { OverlayViewController *o = [OverlayViewController sharedOverlayViewController]; [self.view addSubview:o.view]; } 

Exemple de code que vous pouvez utiliser pour afficher votre vue modale:

 [[OverlayViewController sharedOverlayViewController] presentModalViewController:myModalViewController animated:YES]; 

Je n’ai pas vraiment utilisé -presentModalViewController:animated: avec mon OverlayViewController mais je pense que cela fonctionnerait très bien.

Voir aussi: À quoi ressemble votre singleton Objective-C?

J’ai eu le même problème et la solution est d’append la vue modale avec addSubview: et d’animer le changement dans la hiérarchie des vues avec animateWithDuration d’UIView: delay: options: animations: completion:

J’ai ajouté une propriété et 2 méthodes à une sous-classe de UIViewController (FRRViewController) qui inclut d’autres fonctionnalités. Je publierai bientôt tout le contenu sur gitHub, mais vous pourrez voir le code ci-dessous. Pour plus d’informations, vous pouvez consulter mon blog: Comment afficher un contrôleur de vue modal transparent .

 #pragma mark - Transparent Modal View -(void) presentTransparentModalViewController: (UIViewController *) aViewController animated: (BOOL) isAnimated withAlpha: (CGFloat) anAlpha{ self.transparentModalViewController = aViewController; UIView *view = aViewController.view; view.opaque = NO; view.alpha = anAlpha; [view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *each = obj; each.opaque = NO; each.alpha = anAlpha; }]; if (isAnimated) { //Animated CGRect mainrect = [[UIScreen mainScreen] bounds]; CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height); [self.view addSubview:view]; view.frame = newRect; [UIView animateWithDuration:0.8 animations:^{ view.frame = mainrect; } completion:^(BOOL finished) { //nop }]; }else{ view.frame = [[UIScreen mainScreen] bounds]; [self.view addSubview:view]; } } -(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{ if (animated) { CGRect mainrect = [[UIScreen mainScreen] bounds]; CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height); [UIView animateWithDuration:0.8 animations:^{ self.transparentModalViewController.view.frame = newRect; } completion:^(BOOL finished) { [self.transparentModalViewController.view removeFromSuperview]; self.transparentModalViewController = nil; }]; } } 

Voici ce que j’ai fait pour résoudre le problème – Google les détails, mais cette approche a très bien fonctionné pour moi:

  • Prenez une capture d’écran de la vue sous-jacente. https://devforums.apple.com/message/266836 – cela conduit à une méthode prête à l’emploi qui renvoie un UIView pour l’écran en cours.
  • Remettez la capture d’écran à la vue modale (j’ai utilisé une propriété)
  • Présenter la vue modale
  • Dans viewDidAppear du contrôleur de vue modale, définissez l’image comme UIImageView à l’index 0. Ajustez la position verticale de l’image en fonction de la hauteur de la barre d’état.
  • Dans le viewWillDisappear du contrôleur de la vue modale, supprimez à nouveau l’image

L’effet est:

  • La vue s’anime comme n’importe quelle vue modale – les parties semi-transparentes de la vue modale glissent sur la vue existante
  • Dès que l’animation s’arrête, l’arrière-plan est défini sur la capture d’écran, ce qui donne l’impression que l’ancienne vue est toujours en dessous, même si ce n’est pas le cas.
  • Dès que l’animation de disparition de la vue modale commence, l’image est supprimée. Le système d’exploitation affiche quant à lui l’ancienne vue de navigation, de sorte que la vue modale glisse de manière transparente et invisible, comme prévu.

J’ai essayé de l’animer dans ma propre vue superposée mais cela n’a pas très bien fonctionné. J’ai eu un accident sans indication de ce qui s’est écrasé. Plutôt que de courir après cela, j’ai fait le bg view & Works vraiment bien.

Code dans la vue modale – Je pense que vous pouvez déterminer le rest, à savoir la définition de la propriété modalView.bgImage …

 - (void)viewDidAppear:(BOOL)animated { // background // Get status bar frame dimensions CGRect statusBarRect = [[UIApplication sharedApplication] statusBarFrame]; UIImageView *imageView = [[UIImageView alloc] initWithImage:self.bgImage]; imageView.tag = 5; imageView.center = CGPointMake(imageView.center.x, imageView.center.y - statusBarRect.size.height); [self.view insertSubview:imageView atIndex:0]; } - (void)viewWillDisappear:(BOOL)animated { [[self.view viewWithTag:5] removeFromSuperview]; } 
 self.modalPresentationStyle = UIModalPresentationCurrentContext; [self presentModalViewController:newview animated:YES]; 

et assurez-vous que l’arrière-plan de la vue modale est transparent,

self.view.background = …. alpha: 0.x;

Si vous définissez modalPresentationStyle pour le contrôleur de vue modal sur:

viewController.modalPresentationStyle = 17;

La vue en arrière-plan n’est pas supprimée. (TWTweetComposeViewController l’utilise).

Je n’ai pas essayé de passer l’examen de l’App Store avec ce code si

Cet article sur l’ affichage d’une vue “Loading …” semi-transparente pourrait donner quelques indications sur la manière de procéder.

Ouais, vous devez append la vue manuellement, et si vous voulez glisser depuis le bas ou tout ce que vous devez faire l’animation vous-même aussi.

J’ai écrit une classe pour le faire, et un datepicker semi-modal utilisant cette classe comme exemple.

Vous pouvez trouver de la documentation dans cet article de blog , le code est sur github

Je fais des recherches sur ce même problème depuis une semaine. J’ai essayé toutes les différentes réponses et exemples trouvés dans Google et ici sur StackOverflow. Aucun d’entre eux n’a bien travaillé.

Étant nouveau dans la programmation iOS, je n’étais pas au courant de quelque chose appelé UIActionSheet . Donc, si vous essayez d’accomplir ceci pour afficher une superposition modale de boutons (comme un modal demandant à quelqu’un comment ils veulent partager quelque chose), utilisez simplement UIActionSheet .

Voici une page Web qui montre comment faire cela .

J’ai eu cette idée de https://gist.github.com/1279713

Prepare: Dans la vue modale xib (ou la scène utilisant storyboard), je configure le UIImageView d’arrière-plan plein écran (connectez-le avec le fichier .h et donnez-lui une propriété “backgroundImageView”) avec 0.3 alpha. Et j’ai défini la couleur d’arrière-plan de la vue (UIView) comme un noir uni.

Idée: Puis, dans “viewDidLoad” du contrôleur de vue modale, je capture la capture d’écran de l’état d’origine et la place dans l’arrière-plan UIImageView. Définissez le point initial Y sur -480 et laissez-le glisser jusqu’au point Y 0 en utilisant une durée de 0,4 seconde avec l’option d’animation EaseInOut. Lorsque nous rejetons le contrôleur de vue, faites simplement l’inverse.

Code pour la classe de contrôleur de vue modale

Fichier .h:

 @property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView; - (void) backgroundInitialize; - (void) backgroundAnimateIn; - (void) backgroundAnimateOut; 

fichier .m:

 - (void) backgroundInitialize{ UIGraphicsBeginImageContextWithOptions(((UIViewController *)delegate).view.window.frame.size, YES, 0.0); [((UIViewController *)delegate).view.window.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); backgroundImageView.image=screenshot; } - (void) backgroundAnimateIn{ CGRect backgroundImageViewRect = backgroundImageView.frame; CGRect backgroundImageViewRectTemp = backgroundImageViewRect; backgroundImageViewRectTemp.origin.y=-480; backgroundImageView.frame=backgroundImageViewRectTemp; [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{ backgroundImageView.frame=backgroundImageViewRect; } completion:^(BOOL finished) { }]; } - (void) backgroundAnimateOut{ CGRect backgroundImageViewRect = backgroundImageView.frame; backgroundImageViewRect.origin.y-=480; [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{ backgroundImageView.frame=backgroundImageViewRect; } completion:^(BOOL finished) { }]; } 

Dans viewDidLoad, appelez simplement:

 [self backgroundInitialize]; [self backgroundAnimateIn]; 

Dans tous les cas où nous rejetons le contrôleur de vue modal, nous appelons:

 [self backgroundAnimateOut]; 

Veuillez noter que cela animera TOUJOURS l’image de fond. Donc, si ce style de transition de contrôleur de vue modal (ou le style de transition de segue) n’est pas défini sur “Cover Vertical”, vous n’aurez peut-être pas besoin d’appeler les méthodes d’animation.

J’ai finalement réalisé ceci, pour une interface de navigation ou une barre d’onglet, en combinant un contrôleur de vue superposé (voir la réponse de pix0r) caché / masqué avant de cacher ou de montrer un contrôleur de vue basé sur ce très bon article .

En ce qui concerne le contrôleur de vue, le conseil est de rendre son affichage en arrière-plan clearColor , puis la vue de recouvrement semi-transparente est visible et toutes les vues ajoutées en tant que sous-vues dans le contrôleur de vue sont avant et surtout opaques.

J’ai créé une librairie soruce ouverte MZFormSheetController pour présenter une feuille de formulaire modale sur UIWindow supplémentaire. Vous pouvez l’utiliser pour présenter le contrôleur de vue modal de transparence, et même pour ajuster la taille du contrôleur de vue présenté.

Pour iOS 8+, vous pouvez utiliser le style de présentation UIModalPresentationOverCurrentContext pour le contrôleur de vue présenté afin de faciliter le comportement souhaité.

 UIViewController *viewController = [[UIViewController alloc] init]; viewController.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.9f]; viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; [self presentViewController:viewController animated:YES completion:nil]; 

Si vous devez également prendre en charge iOS 7 – vérifiez ce fil de discussion .

Vous pouvez obtenir un effet de vue modal transparent / semi-transparent en superposant un bouton transparent / semi-transparent à la fois dans la vue et dans la barre de navigation.

Vous pouvez accéder à la barre de navigation via la propriété navigationBar de UINavigationController.

J’ai trouvé qu’UIButton, contrairement à UILabel, piège les événements de souris, ce qui donne le comportement modal correct.

Je viens de trouver une solution pour cela. Créez simplement 1X1 de UIViewController et ajoutez-le à votre contrôleur de vue parent. Et afficher le contrôleur de vue modal transparent dans cet UIViewController.

sur viewDidLoad;

self.dummyViewController = [[UIViewController alloc] init]; [self.dummyViewController.view setFrame: CGRectMake (0, 0, 1, 1)]; [self.view addSubView: self.dummyViewController.view];

quand vous avez besoin d’ouvrir un transparentViewController;

[self.dummyViewController presentModalViewController: votreTransparentModalViewController animé: true];

Si vous avez besoin d’un écran comme celui ci-joint, le code ci-dessous peut vous aider. entrer la description de l'image ici

Le code:

 MyViewController * myViewController = [[MyViewController alloc] initWithNibName:nibName bundle:nil]; UINavigationController * myNavigationController = [[UINavigationController alloc] initWithRootViewController: myViewController]; myNavigationController.modalPresentationStyle = UIModalPresentationPageSheet; [self presentModalViewController: myNavigationController animated:YES]; 

Si vous voulez une superposition d’écran, utilisez la vue parentViewController.view, elle se placera au-dessus de la barre de navigation ++

MyCustomViewController* myOverlayView = [[MyCustomViewController alloc] init]; [self.parentViewController.view addSubview:myOverlayView];

Cela a fonctionné pour moi:

 UIViewController *modalViewController = [[UIViewController alloc] init]; modalViewController.view.backgroundColor = [UIColor whiteColor] colorWithAlpha:0.5]; [self showDetailViewController:modalViewController sender:nil];