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+.