Ich versuche, einen View-Controller mit transparentem Hintergrund modal darzustellen. Mein Ziel ist es, die Ansicht der präsentierten und der präsentierten Ansichtssteuerung gleichzeitig anzeigen zu lassen. Das Problem ist, wenn die Präsentation der Präsentation beendet ist, verschwindet die Ansicht des Präsentationsansicht-Controllers.
- (IBAction)pushModalViewControllerButtonPressed:(id)sender
{
ModalViewController *modalVC = [[ModalViewController alloc] init];
[self presentViewController:modalVC animated:YES completion:nil];
}
Ich weiß, ich könnte die Ansicht einfach als Unteransicht hinzufügen, aber ich möchte diese Lösung aus irgendeinem Grund vermeiden. Wie könnte ich das beheben?
Dieser folgende Code funktioniert nur auf dem iPad.
self.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:modalVC animated:YES];
Ich würde eine Unteransicht hinzufügen.
Hier ist eine sehr gute Diskussion. Schauen Sie sich die Kommentare genau an. Nicht nur die Antwort.
Wenn ich du wäre, würde ich es nicht tun. Ich würde eine Unteransicht hinzufügen und es tun. Es scheint mir eine bessere Kontrolle über die Dinge zu geben.
EDIT:
Wie von Paul Linsay erwähnt, ist seit iOS 8 alles, was benötigt wird, UIModalPresentationOverFullScreen
für den modalPresentationStyle des ViewControllers. Dies würde auch die Schaltflächen navigationBar und tabBar umfassen.
Für diejenigen, die versuchen, dies unter iOS 8 zu erreichen, besteht die "von Apple genehmigte" Methode zur Anzeige eines transparenten Modal View-Controllers darin, modalPresentationStyle
auf dem aktuellen ed Controller auf UIModalPresentationOverCurrentContext
zu setzen.
Dies kann im Code erfolgen oder durch Festlegen der Eigenschaften des Segments im Storyboard.
Aus der UIViewController-Dokumentation:
UIModalPresentationOverCurrentContext
Ein Präsentationsstil, bei dem der Inhalt nur über .__ angezeigt wird. Inhalt des übergeordneten View-Controllers. Die Ansichten unter der präsentierten Inhalt wird nicht aus der Ansichtshierarchie entfernt, wenn die Präsentation endet. Wenn also der dargestellte View-Controller den Bildschirm nicht ausfüllt mit undurchsichtigen Inhalten wird der zugrunde liegende Inhalt durchscheint.
Bei der Darstellung eines View-Controllers in einem Popover wird diese Präsentation style wird nur unterstützt, wenn der Übergangsstil .__ ist. UIModalTransitionStyleCoverVertical. Versuch, ein anderes .__ zu verwenden. Übergangsstil löst eine Ausnahme aus. Sie können jedoch auch andere .__ verwenden. Übergangsstile (mit Ausnahme des partiellen Curl-Übergangs), wenn das übergeordnete Element View Controller befindet sich nicht in einem Popover.
Verfügbar in iOS 8.0 und höher.
https://developer.Apple.com/documentation/uikit/uiviewcontroller
Das Video "View Controller Advancements in iOS 8" von der WWDC 2014 geht ausführlich darauf ein.
Hinweis:
viewDidLoad
des PresentationViewControllers hat keine AuswirkungenIn iOS 8.0 und höher kann dies durch Setzen der Eigenschaft modalPresentationStyle auf UIModalPresentationOverCurrentContext erfolgen
//Set property **definesPresentationContext** YES to avoid presenting over presenting-viewController's navigation bar
self.definesPresentationContext = YES; //self is presenting view controller
presentedController.view.backgroundColor = [YOUR_COLOR with alpha OR clearColor]
presentedController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:presentedController animated:YES completion:nil];
Dieser Code funktioniert auf dem iPhone unter iOS6 und iOS7 gut:
presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];
In diesem Fall verpassen Sie eine Slide-On-Animation. Um die Animation beizubehalten, können Sie noch die folgende "nicht elegante" Erweiterung verwenden:
[presentingVC presentViewController:presentedVC animated:YES completion:^{
[presentedVC dismissViewControllerAnimated:NO completion:^{
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:NO completion:NULL];
}];
}];
Wenn sich unser PresentingV im UINavigationController oder UITabbarController befindet, müssen Sie diese Controller als PresentingVC verwenden.
In iOS7 können Sie außerdem eine benutzerdefinierte Übergangsanimation mithilfe des UIViewControllerTransitioningDelegate
-Protokolls implementieren. In diesem Fall können Sie natürlich einen transparenten Hintergrund erhalten
@interface ModalViewController : UIViewController <UIViewControllerTransitioningDelegate>
Bevor Sie präsentieren, müssen Sie modalPresentationStyle
einstellen.
modalViewController.modalPresentationStyle = UIModalPresentationCustom;
Dann müssen Sie zwei Protokollmethoden implementieren
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
CustomAnimatedTransitioning *transitioning = [CustomAnimatedTransitioning new];
transitioning.presenting = YES;
return transitioning;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
CustomAnimatedTransitioning * transitioning = [CustomAnimatedTransitioning new];
transitioning.presenting = NO;
return transitioning;
}
Als letztes müssen Sie Ihren benutzerdefinierten Übergang in der Klasse CustomAnimatedTransitioning
definieren
@interface CustomAnimatedTransitioning : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end
@implementation CurrentContextTransitionAnimator
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.25;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting) {
// custom presenting animation
}
else {
// custom dismissing animation
}
}
Ich habe ein wenig mit dem Interface Builder von XCode 7 gekämpft, um den Präsentationsstil als @VenuGopalTewari vorgeschlagen zu setzen. In dieser Version scheint es keinen Over Current Context
- oder Over Full Screen
-Präsentationsmodus für das Segment zu geben. Damit das funktioniert, setze ich den Modus auf Default
:
Zusätzlich habe ich den Präsentationsmodus des modal dargestellten View-Controllers auf Over Full Screen
eingestellt:
Erstellen Sie ein Segment, um es modal darzustellen, und legen Sie die Presentation-Eigenschaft dieses Segments auf den aktuellen Kontext festIt funktioniert 100%.
PresentViewController mit transparentem Hintergrund - in iOS 8 und iOS 9
MYViewController *myVC = [self.storyboard instantiateViewControllerWithIdentifier:@"MYViewController"];
myVC.providesPresentationContextTransitionStyle = YES;
myVC.definesPresentationContext = YES;
[myVC setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self.navigationController presentViewController:myVC animated:YES completion:nil];
Und in MYViewController die Hintergrundfarbe schwarz einstellen und die Deckkraft verringern
Es ist ein bisschen gehackt, aber für mich funktioniert dieser Code (iOS 6):
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[self presentViewController:self.signInViewController animated:YES completion:^{
[self.signInViewController dismissViewControllerAnimated:NO completion:^{
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:self.signInViewController animated:NO completion:nil];
appDelegate.window.rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
}];
}];
Dieser Code funktioniert auch auf dem iPhone
Diese Kategorie arbeitete für mich (iOS 7, 8 und 9)
H-Datei
@interface UIViewController (navigation)
- (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end
M-Datei
@implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
[self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];
}else{
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
UIViewController *presentingVC = self;
UIViewController *root = self;
while (root.parentViewController) {
root = root.parentViewController;
}
UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
root.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
root.modalPresentationStyle = orginalStyle;
}];
}
@end
Wenn Sie das Storyboard verwenden, können Sie diesen Schritt ausführen:
- Fügen Sie einen View Controller (V2) hinzu, und richten Sie die Benutzeroberfläche wie gewünscht ein
V2 modal präsentieren
Klicken Sie auf das Segue. Legen Sie im Eigenschafteninspektor die Option Präsentation als Über Vollbild fest. Entfernen Sie die Animation, wenn Sie möchten
- Wählen Sie V2 aus. Legen Sie im Eigenschafteninspektor die Option Präsentation als Über Vollbild fest. Check Definiert den Kontext und stellt den Kontext bereit
- Wählen Sie die Hauptansicht Ihrer V2 (Bitte überprüfen Sie das Bild). Setze backgroundColor auf Farbe löschen
Ich habe diese drei Zeilen in der init-Methode im vorgestellten View-Controller hinzugefügt und funktioniert wie ein Zauber:
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[self setModalPresentationStyle:UIModalPresentationOverCurrentContext];
BEARBEITEN (arbeitet an iOS 9.3):
self.modalPresentationStyle = UIModalPresentationOverFullScreen;
Wie in der Dokumentation:
UIModalPresentationOverFullScreen Ein Darstellungsstil der Ansicht, in dem die dargestellte Ansicht den Bildschirm abdeckt. Die Ansichten unter dem präsentierten Inhalt werden nach Abschluss der Präsentation nicht aus der Ansichtshierarchie entfernt. Wenn also der dargestellte View-Controller den Bildschirm nicht mit undurchsichtigen Inhalten füllt, wird der zugrunde liegende Inhalt sichtbar.
Verfügbar in iOS 8.0 und höher.
Alternativ können Sie eine "Containeransicht" verwenden. Einfach Alpha unter 1 machen und mit Seque einbetten. XCode 5, Ziel iOS7. Auf dem iPhone getestet.
Containeransicht verfügbar unter iOS6 . Link zum Blogbeitrag darüber.
Die Lösung für diese Antwort mit Swift wäre wie folgt.
let vc = MyViewController()
vc.view.backgroundColor = UIColor.clear // or whatever color.
vc.modalPresentationStyle = .overCurrentContent
present(vc, animated: true, completion: nil)
Ich habe ein Objekt erstellt, das die Darstellung eines "überlagerten Modals" behandelt, das heißt, es behält die Ansicht des Hintergrunds bei und ermöglicht Ihnen, einen Modal mit transparentem Hintergrund zu haben.
Es gibt eine einfache Methode, die dies ausführt:
- (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];
}
Es ist wichtig, die modalPresentationCapturesStatusBarAppearance
-Eigenschaft auf YES
zu setzen und die Aktualisierung der Statusleiste zu erzwingen, wenn Ihr präsentierter View-Controller eine andere preferredStatusBarStyle
hat.
Dieses Objekt sollte eine @property (assign, nonatommic) isPresenting
haben
Sie möchten, dass dieses Objekt den Protokollen UIViewControllerAnimatedTransitioning
und UIViewControllerTransitioningDelegate
entspricht und die folgenden Methoden implementiert:
- (id)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
self.isPresenting = YES;
return self;
}
- (id)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.isPresenting = NO;
return self;
}
und:
- (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];
}];
}
}
Dabei wird eine Animation von der Unterseite nach unten der Standard-Modal-Animation nachgebildet. Sie können sie jedoch beliebig gestalten.
Wichtig ist, dass die Ansicht des Presenting View Controllers hinten bleibt, sodass Sie einen transparenten Effekt erzeugen können.
Diese Lösung funktioniert für iOS 7+
Eine sehr einfache Möglichkeit, dies zu tun (beispielsweise mit Storyboards
), ist:
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
}];
Dadurch wird eine UIViewController
in einer Storyboard
modal dargestellt, jedoch mit einem durchscheinenden Hintergrund.
Arbeiten für iOS 7-10
if #available(iOS 8.0, *) {
nextVC.modalPresentationStyle = .OverCurrentContext
self.presentViewController(nextVC, animated: true, completion: nil)
} else {
// Fallback on earlier version
self.modalPresentationStyle = .Custom
nextVC.modalTransitionStyle = .CrossDissolve
self.presentViewController(nextVC, animated: false, completion: nil)
}
}
Um alle guten Antworten und Kommentare hier zusammenzufassen und trotzdem eine Animation zu haben, während Sie zu Ihrer neuen ViewController
wechseln, habe ich Folgendes getan: (Unterstützt iOS 6 und höher)
Wenn Sie eine UINavigationController
\UITabBarController
verwenden, gehen Sie wie folgt vor:
SomeViewController *vcThatWillBeDisplayed = [self.storyboard instantiateViewControllerWithIdentifier:@"SomeVC"];
vcThatWillBeDisplayed.view.backgroundColor = [UIColor colorWithRed: 255/255.0 green:255/255.0 blue:255/255.0 alpha:0.50];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:presentedVC animated:YES completion:NULL];
Wenn Sie das tun, verlieren Sie Ihre modalTransitionStyle
-Animation. Um dies zu lösen, können Sie Ihrer SomeViewController
-Klasse Folgendes hinzufügen:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[UIView animateWithDuration:0.4 animations:^() {self.view.alpha = 1;}
completion:^(BOOL finished){}];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.alpha = 0;
}
Swift 4.2
guard let someVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someVC") as? someVC else {
return
}
someVC.modalPresentationStyle = .overCurrentContext
present(someVC, animated: true, completion: nil)
Wenn Sie modales Segue verwenden, stellen Sie sicher, dass es als dieses Bild festgelegt ist (Sie können die Animation deaktivieren, wenn Sie möchten)
Natürlich sollten Sie UIModalPresentationCurrentContext einstellen, aber clearColor ist auch sehr wichtig! Sie können den Hintergrund in der viewDidLoad-Funktion nicht festlegen. Setzen Sie ihn vor dem Laden der Ansicht wie in root view controller oder in der init-Funktion des Controllers, der angezeigt wird!
actionController.view.backgroundColor = [UIColor clearColor];
[self presentViewController:actionController animated:YES completion:nil];
oder
- (instancetype)init {
self = [super initWithNibName:nil bundle:nil];
if(self) {
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self.view setBackgroundColor:[UIColor clearColor]];
}
return self;
}
Eine vollständige Methode, die auf iOS 7 und iOS 8 getestet wurde.
@interface UIViewController (MBOverCurrentContextModalPresenting)
/// @warning Some method of viewControllerToPresent will called twice before iOS 8, e.g. viewWillAppear:.
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
@end
@implementation UIViewController (MBOverCurrentContextModalPresenting)
- (void)MBOverCurrentContextPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
UIViewController *presentingVC = self;
// iOS 8 before
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
UIViewController *root = presentingVC;
while (root.parentViewController) {
root = root.parentViewController;
}
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
[viewControllerToPresent dismissViewControllerAnimated:NO completion:^{
UIModalPresentationStyle orginalStyle = root.modalPresentationStyle;
if (orginalStyle != UIModalPresentationCurrentContext) {
root.modalPresentationStyle = UIModalPresentationCurrentContext;
}
[presentingVC presentViewController:viewControllerToPresent animated:NO completion:completion];
if (orginalStyle != UIModalPresentationCurrentContext) {
root.modalPresentationStyle = orginalStyle;
}
}];
}];
return;
}
UIModalPresentationStyle orginalStyle = viewControllerToPresent.modalPresentationStyle;
if (orginalStyle != UIModalPresentationOverCurrentContext) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:completion];
if (orginalStyle != UIModalPresentationOverCurrentContext) {
viewControllerToPresent.modalPresentationStyle = orginalStyle;
}
}
@end
Setze modalPresentationStyle
der Navigation auf UIModalPresentationCustom
und legen Sie die Hintergrundfarbe Ihres präsentierten View-Controllers als klare Farbe fest.
in appdelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[_window rootViewController]setModalPresentationStyle:UIModalPresentationCurrentContext];
return YES;
}
in Ihrer ersten Ansicht Controller, von wo aus Sie die nächste Ansicht laden müssen:
NextViewController *customvc = [[NextViewController alloc]init];
[self presentViewController:customvc animated:YES completion:^{
}];
in Ihrem nextViewController der transparent hinzugefügt werden soll:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
UIView* backView = [[UIView alloc] initWithFrame:self.view.frame];
backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
[self.view insertSubview:backView atIndex:0];
}
Der Anmeldebildschirm ist modal, dh er befindet sich oben auf dem vorherigen Bildschirm. Bisher haben wir unscharfen Hintergrund, aber es verwischt nichts. es ist nur ein grauer Hintergrund.
Zuerst müssen wir den Ansichtshintergrund des View Controllers in Farbe löschen ändern. Es bedeutet einfach, dass es transparent sein sollte. Diese Ansicht ist standardmäßig weiß.
Zweitens müssen Sie den Segue auswählen, der zum Anmeldebildschirm führt, und im Attributinspektor die Darstellung auf Over Current Context setzen. Diese Option ist nur verfügbar, wenn Auto-Layout und Größenklassen aktiviert sind.