web-dev-qa-db-fra.com

iOS - Contrôleur de vue modale semi-transparent

Je souhaite présenter un contrôleur de vue avec un arrière-plan légèrement transparent de façon modale sur la vue actuelle, de sorte que la première vue soit légèrement visible sous la vue modale.

J'ai défini la valeur alpha du contrôleur de vue modale et défini le modalPresentationStyle sur UIModalPresentationCurrentContext, comme suggéré dans un autre post.

Le résultat est que l'arrière-plan de la vue est transparent lors de l'animation, mais lorsque le contrôleur de vue est en place, il devient noir opaque. Il redevient transparent tout en animant le licenciement.

Comment puis-je le rendre transparent lorsqu'il est actif?

J'ai testé en iOS 6 and 7. Le code que j'utilise est le suivant:

MyModalViewController *viewController = [[MyModalViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
[navController setNavigationBarHidden:YES];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self.navigationController presentViewController:navController animated:YES completion:NULL];
24
Drew C

iOS 8 a ajouté un nouveau style de présentation modale spécialement à cet effet:

presentedViewController.modalPresentationStyle = UIModalPresentationOverFullScreen

De la spec :

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 supprimées de la hiérarchie des vues lorsque la présentation se termine. Donc, si le contrôleur de vue présenté ne remplit pas l'écran de contenu opaque, le contenu sous-jacent apparaît.

40
jburns20

Si vous ciblez ios 8 et supérieur, vous pouvez définir le style de présentation modale sur "dans le contexte actuel" et vous avez terminé. Si ios 7 et versions antérieures, vous devez créer un style de transition personnalisé afin que l'écran de présentation ne se vide pas après la transition. C'est assez compliqué.

La solution que je présente offre beaucoup de flexibilité: faites une capture d'écran avant d'afficher la boîte de dialogue modale et définissez-la comme image de fond pour la fenêtre de l'application. Par défaut, cet arrière-plan est noir (c'est ce que vous voyez lorsque le contrôleur de vue arrière disparaît). Remplacez l'arrière-plan par la capture d'écran de l'application. Faites la capture d'écran dans la méthode viewWillAppear ou viewDidLoad de votre vue transparente. Cela fonctionne même avec les séquences Push, non seulement les boîtes de dialogue modales, mais vous devez éviter les animations. En général, évitez les animations qui affectent la position de la vue d'arrière-plan, car elles donneront l'impression qu'elle se remet en place à la fin de la transition. C'est une bonne idée de réinitialiser l'arrière-plan à sa précédente image noire sur viewDidDissapear pour éviter les effets indésirables.

Vous pouvez conserver une pile de ces images d'arrière-plan et vous pouvez effectuer plusieurs séques Push "transparents". Ou avoir un menu complexe/profond qui apparaît au-dessus d'un écran principal. Pour ces nombreuses raisons, je pense que cette solution est meilleure que de rouler votre propre code de transition. Il est plus flexible et plus facile à implémenter, et vous n'avez pas à gérer vous-même les animations.

3
Radu Simionescu

La raison pour laquelle les contrôleurs de vue BG disparaissent après l'affichage d'un modal est que la transition par défaut dans iOS 7 supprime la vue BG une fois l'animation terminée. Si vous définissez votre propre transition et que vous définissez votre vue BG pour qu'elle ne soit pas supprimée (en changeant simplement son alpha), vous aurez alors la vue modale transparente.

2
Ali Ersöz

Le même problème m'est apparu. Je l'ai résolu en regardant l'url suivante à propos d'un contrôleur d'alerte personnalisé . J'ai réussi à le faire fonctionner même avec un UINavigationController.

Swift

let viewController = UIViewController()
viewController.providesPresentationContextTransitionStyle = true
viewController.definesPresentationContext = true
viewController.modalPresentationStyle = .overCurrentContext
viewController.modalTransitionStyle = .crossDissolve
DispatchQueue.main.async {
    self.navigationController?.present(viewController, animated: true, completion: nil)
}

Objectif c

UIViewController *viewController = [UIViewController new];
viewController.providesPresentationContextTransitionStyle = true;
viewController.definesPresentationContext = true;
viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

dispatch_async(dispatch_get_main_queue(), ^{
    [self.navigationController presentViewController:viewController animated:true completion:nil];
});
2
Craz1k0ek

FYI: La syntaxe est maintenant:

    childVC.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
1
Eden

Ma solution est la suivante:

Créez une superposition UIView transparente personnalisée qui vient sur n'importe quelle vue, barre de navigation et barre de tabulations.

-Dans le contrôleur de navigation (ou contrôleur de barre d'onglets) dans lequel votre contrôleur de vue est intégré, je crée une vue personnalisée avec son cadre égal au cadre de la vue du contrôleur de navigation.

-Puis je l'ai réglé hors écran en définissant son Origin.y sur navigationController.view.height

-Puis je crée 2 fonctions - (void) showOverlay et - (void) hideOverlay qui animent la vue de superposition sur et hors écran:

- (void)hideOverlay{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.3];

    CGRect frm = self.helpView.frame;//helpView is my overlay
    frm.Origin.y = self.offscreenOffset; //this is an Y offscreen usually self.view.height
    self.helpView.frame = frm;

    [UIView commitAnimations];
}

- (void)showOverlay{

    [self.view bringSubviewToFront:self.helpView];

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.3];

    CGRect frm = self.helpView.frame;
    frm.Origin.y = self.onscreenOffset;
    self.helpView.frame = frm;

    [UIView commitAnimations];
}

-Dans mon contrôleur de vue, je peux simplement appeler

[(MyCustomNavCtrl *)self.navigationController showOverlay];
[(MyCustomNavCtrl *)self.navigationController hideOverlay];

Et c'est tout.

1
user1670679

Voici une solution.

Créez votre contrôleur de vue de présentation. Ajoutez une vue arrière à la vue principale de ce contrôleur de vue. Nommez ceci comme backView.

Dans SecondViewController.m

-(void)viewDidLoad
{
    // Make the main view's background clear, the second view's background transparent.
    self.view.backgroundColor = [UIColor clearColor];
    UIView* backView = [[UIView alloc] initWithFrame:self.view.frame];
    backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
    [self.view addSubview:backView];
}

Vous avez maintenant un contrôleur de vue avec un fond à moitié transparent. Vous pouvez ajouter tout ce que vous voulez au self.view, le reste sera à moitié transparent.

Après cela, dans FirstViewController.m

self.modalPresentationStyle = UIModalPresentationCurrentContext;

[self presentViewController:secondViewController animated:YES completion:nil];
1
alper_k