Wyświetl clearColor UIViewController przez UIViewController


150

Mam UIViewControllerwidok jako widok podrzędny / modalny na wierzchu innego UIViewControllerwidoku, na przykład widok podrzędny / widok modalny powinien być przezroczysty i wszystkie komponenty dodane do widoku podrzędnego powinny być widoczne. Problem polega na tym, że u mnie podwidok pokazuje czarne tło zamiast mieć clearColor. Staram się, aby UIViewtło było jasne, a nie czarne. Czy ktoś wie, co jest z tym nie tak? Wszelkie sugestie są mile widziane.

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];
}

ROZWIĄZANE : naprawiłem problemy. Działa tak dobrze zarówno na iPhonie, jak i iPadzie. Modalny kontroler widoku bez czarnego tła po prostu przezroczysty / przezroczysty. Jedyne, co trzeba zmienić to Wymieniłem UIModalPresentationFullScreensię UIModalPresentationCurrentContext. Jakie to proste!

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];

UWAGA: Jeśli używasz modalPresentationStylewłaściwości 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];

UWAGA: Zła wiadomość jest taka, że ​​powyższe rozwiązanie nie działa na iOS 7. Dobrą wiadomością jest to, że naprawiłem problem z iOS7! Poprosiłem kogoś o pomoc i oto co powiedział:

Podczas prezentacji kontrolera widoku modalnie system iOS usuwa kontrolery widoku znajdujące się pod nim z hierarchii widoku na czas, w którym jest prezentowany. Chociaż widok kontrolera widoku prezentowanego modalnie jest przezroczysty, pod nim nie ma nic poza oknem aplikacji, które jest czarne. iOS 7 wprowadził nowy modalny styl prezentacji UIModalPresentationCustom, który powoduje, że iOS nie usuwa widoków pod prezentowanym kontrolerem widoku. Jednak aby użyć tego modalnego stylu prezentacji, musisz zapewnić własnego delegata przejścia do obsługi prezentacji i odrzucania animacji. Jest to opisane w wykładzie „Niestandardowe przejścia przy użyciu kontrolerów widoku” z WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, w którym omówiono również, jak zaimplementować własnego delegata przejścia.

Możesz zobaczyć moje rozwiązanie powyższego problemu w iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions


1
upewnij się, że ustawiłeś modalPresentationStyle w rootViewController, w przeciwnym razie to nie zadziała
Thorsten

Spójrz na komentarz do tej odpowiedzi stackoverflow.com/a/25990081/1418457 , to działa
onmyway133

Ten stackoverflow.com/q/27598846/1603234 sprawia, że ​​się uśmiecham, teraz twoja kolej :)
Hemang,

Musiałem zrobić self.modalPresentationStyle = UIModalPresentationCurrentContext; z prezentowanym kontrolerem widoku, aby działał, a nie z prezentującym.
Tulleb

1
Sprawdź odpowiedź Brody'ego poniżej. modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; rozwiąże problem,
GoodSp33d

Odpowiedzi:


143

iOS8 +

W iOS8 + możesz teraz użyć nowego modalPresentationStyle UIModalPresentationOverCurrentContext, aby przedstawić kontroler widoku z przezroczystym tłem:

MyModalViewController *modalViewController = [[MyModalViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;           
[self presentViewController:modalViewController animated:YES completion:nil];    

5
Powinna być zaakceptowana odpowiedź. Wcześniej zaakceptowana odpowiedź jest nadal ważna ze względu na starsze wersje, ale jest to metoda zalecana.
Tomasz Bąk

3
Jeśli tworzysz tylko dla iOS 8, skorzystaj z tej odpowiedzi! To działa
Mário Carvalho

2
To dobrze, ale czy nie powinno być w ostatniej linijce [self presentViewController:modalViewController animated:YES completion:nil];? (zamiast targetController)?
SuperDuperTango

3
Aby to dla mnie zadziałało dodałem modalViewController.view.backgroundColor = UIColor.clearColor () dzięki za rozwiązanie
Pramod

czy ktoś może mi też podać kod do pushviewcontroller (mam na myśli kontroler nawigacji).
Alok

140

ZDECYDOWANY : naprawiłem problemy. Działa tak dobrze zarówno na iPhonie, jak i iPadzie. Modalny kontroler widoku bez czarnego tła po prostu przezroczysty / przezroczysty. Jedyną rzeczą, którą muszę zmienić, jest zastąpienie UIModalPresentationFullScreen na UIModalPresentationCurrentContext. Jakie to proste!

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];

UWAGA: Jeśli używasz właściwości modalPresentationStyle nawigacjiController:

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];

UWAGA: Zła wiadomość jest taka, że ​​powyższe rozwiązanie nie działa na iOS 7. Dobrą wiadomością jest to, że naprawiłem problem z iOS7! Poprosiłem kogoś o pomoc i oto co powiedział:

Podczas prezentacji kontrolera widoku modalnie system iOS usuwa kontrolery widoku znajdujące się pod nim z hierarchii widoku na czas, w którym jest prezentowany. Chociaż widok kontrolera widoku prezentowanego modalnie jest przezroczysty, pod nim nie ma nic oprócz okna aplikacji, które jest czarne. iOS 7 wprowadził nowy modalny styl prezentacji, UIModalPresentationCustom, który powoduje, że iOS nie usuwa widoków pod prezentowanym kontrolerem widoku. Jednak aby użyć tego modalnego stylu prezentacji, musisz zapewnić własnego delegata przejścia do obsługi prezentacji i odrzucania animacji. Jest to opisane w wykładzie „Niestandardowe przejścia przy użyciu kontrolerów widoku” z WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, w którym omówiono również, jak zaimplementować własnego delegata przejścia.

Możesz zobaczyć moje rozwiązanie powyższego problemu w iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions


1
self.modalPresentationStyle = UIModalPresentationCurrentContext;zrobił to.
Adriano Lucas

4
btw .. Zauważyłem, że z powodu self.modalPresentationStyle = UIModalPresentationCurrentContext; nie przedstawia modalViewController z animacją .. jakieś pomysły?
Devarshi

1
@Miraaj Następnie ustaw modalPresentationStyle z powrotem na UIModalPresentationFullScreen przed wyświetleniem UIViewController powinno działaćself.modalPresentationStyle = UIModalPresentationFullScreen; [self performSegueWithIdentifier:@"CustomSegue" sender:self];
hightech

1
Uruchamiając to w iOS 6 i 7, nowy kontroler widoku jest wyraźny podczas animowania prezentacji, ale po jego umieszczeniu tło staje się czarne. Podczas animacji zwolnienia znów staje się jasne. Czy ktoś inny miał ten problem?
Drew C,

3
@pkamb Zaktualizowałem rozwiązanie dla iOS 7. stackoverflow.com/a/11252969/1344459 Mam nadzieję, że to Ci pomoże.
zaawansowane technologicznie

114

Więc dla czysto wizualnych myślicieli i fanów storyboardów możesz zrobić:

1. Prezentacja kontrolera widoku

Zdefiniuj kontekst

2. Kontroler widoku prezentowanego

Prezentacja: w obecnym kontekście


To powinna być akceptowana odpowiedź. To wszystko, co musisz zrobić, aby to zadziałało, a następnie ustaw kolor tła widoku na kontrolerze modalnym na wyczyść.
Jesse

Zgoda, w tym przypadku opcje scenorysu zastępują kod.
C0D3

17
Ta odpowiedź jest taka słodka, teraz mam cukrzycę.
GeneCode

25

Rozwiązanie Swift 3 i 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)

16

To pochodzi z xCode 7 beta 4 przy użyciu kontrolnego przeciągania płynnego. Po prostu ustaw tło miejsca docelowego, aby wyczyścić, i ustaw właściwości przejścia w IB w następujący sposób (uwaga. Prezentacja może być również „Na pełnym ekranie”):

wprowadź opis obrazu tutaj


2
DZIĘKUJĘ CI. Naprawiłem twoją segue + odpowiedź ViewControllers autorstwa @pasevin i zadziałało !!
CSawy

1
To odpowiedziała na moje pytanie. Dziękuję Ci bardzo. Głos
pozytywny

8

Znalazłem najłatwiejszy sposób, aby to działało na iOS7 i iOS8, to dodanie set PresentationStyle do UIModalPresentationOverCurrentContext na modallyPresentedVC (ViewController, który chcesz przedstawić modalnie) z powodu iOS8:

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

i UIModalPresentationCurrentContext na presentVC (kontrolerze, który prezentuje modallyPresented) z powodu iOS7:

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

Ponieważ sprawy są obsługiwane inaczej na iOS7 i iOS8. Oczywiście nie musisz ustawiać właściwości navigationController, jeśli ich nie używasz. Mam nadzieję, że to pomoże.


uratował mój bekon! Dzięki
Duck

5

Wersja 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)

4

Inny sposób (nie ma potrzeby tworzenia niestandardowego przejścia i działa na iOS 7)

Korzystanie ze scenorysu:

Utwórz kontroler widoku podrzędnego z dowolnym rozmiarem, ustaw szerokość widoku na 500x500 (na przykład) i dodaj następną metodę:

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

Następnie utwórz segue modalne za pomocą Arkusza formularzy i przetestuj je.


Jesteś niesamowity!!! to faktycznie działa !!! (ustawienie rozmiaru „swobody” w IB nie ma żadnego wpływu, ponieważ jest to miara symulowana, ale i tak działa !!!) i jest takie proste !!!
Radu Simionescu

4

Rozwiązanie iOS 7 z niestandardowym segue:

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

Rozwiązanie oparte na najnowocześniejszym kodzie.


Kiedy odrzucam przez [self dismissViewControllerAnimated: YES ukończenie: NULL]; Mam wyjątek?
Asadullah Ali

Tak dla tego kodu. Lub musisz zaimplementować metodę animationControllerForDismissedController, aby animacja zaczęła działać.
Max Gribov

4

Dla mnie to działa:

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];

MMPushNotificationViewControllerjest kontrolerem widoku przezroczystego, a także MMPushNotificationViewControllerustawiłem kolor widoku jako clearcolor. Teraz wszystko, co zrobiłem i zrobiłem mój Transparentviewcontroller.


2

Dla iOS7

Jest teraz sposób na osiągnięcie tego za pomocą niestandardowych przejść iOS7, w ten sposób:

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

Aby utworzyć niestandardowe przejście, potrzebujesz 2 rzeczy:

  • Obiekt TransitionDelegate (implementacja <UIViewControllerTransitionDelegate>)
  • Obiekt „AnimatedTransitioning” (implementacja <UIViewControllerAnimatedTransitioning>)

Więcej informacji na temat niestandardowych przejść można znaleźć w tym samouczku .


Jakieś konkretne powody, dla których dodałeś mainviewcontroller i drugą klasę kontrolera widoku w klasie animatora? dlaczego nie użyłeś bezpośrednio UIViewController * toVC = (UIViewController *) [transitContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [transitContext viewControllerForKey: UITransitionContextFromViewControllerKey];
Satyam Raikar

To nie jest mój samouczek, więc nie wiem, jak to wygląda. Twój punkt wydaje się jednak słuszny.
Kirualex

2

Działa świetnie na iOS7 i 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];

Duplikat drugiej najlepszej odpowiedzi.
Tomasz Bąk

2

Możesz także „ponownie dodać” okno do widoku.

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];

W ten sposób prezentacja może być animowana.


1

W przypadku iOS 7 i tylko przy użyciu Interface Builder można to osiągnąć, ustawiając prezentację na „Over Current Context” na wszystkich kontrolerach widoku zaangażowanych w prezentację modalną. Nawet dla kontrolerów nawigacji.

Na przykład ustaw go na wszystkich tych kontrolerach widoku:

NavController -> RootViewController -> ModalViewController

wprowadź opis obrazu tutaj


0

Nie bawiłem się zbytnio z konstruktorem Storyboard / Interface, ale wyskakuje mi z oczu, że mówisz, że widok jest wyraźny (tj. 100% alfa / przezroczystość), a także mówisz, że jest nieprzezroczysty ( 0% alfa - całkowicie stałe). Te dwie rzeczy nie wydają się być ze sobą powiązane. Zakomentowałbym self.view.opaque = YES;linię i zobaczyłem, czy wtedy zadziała;)

Ach, coś innego, o czym właśnie pomyślałem - jest całkowicie możliwe, że twój kontroler widoku ma tło alfa, ale oczywiście alfa będzie się wyświetlać do koloru okna podstawowego lub kontrolera widoku głównego programu, co jest przez domyślny czarny. Sama warstwa podstawowa całej aplikacji nie może mieć przezroczystego tła - przezroczystego dla czego? Co za tym stoi? Musi być coś, co można zobaczyć PRZEZ przejrzystość. Czy to ma sens?


Próbowałem skomentować self.view.opaque = TAK; linia i nie działa. :-(
highech

Czy przeczytałeś drugą część mojej odpowiedzi? W zależności od konfiguracji możesz nie być w stanie zrobić tego, co chcesz. Co umieszczasz za clearColor VC? Może uda nam się to rozwiązać ^^
WendiKidd

-3

Po prostu użyj „self.modalPresentationStyle = UIModalPresentationCurrentContext;” w widoku prezentacji

Będzie działać dobrze :)


1
To tylko powtórzenie tego, co już powiedziały istniejące odpowiedzi.
Pang
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.