Exibir clearColor UIViewController sobre UIViewController

150

Eu tenho uma UIViewControllervisão como uma subview / modal sobre outra UIViewControllerview, como que a subview / modal deve ser transparente e quaisquer componentes adicionados à subview devem estar visíveis. O problema é que eu tenho é a subview mostra fundo preto em vez de ter clearColor. Estou tentando fazer UIViewcomo um plano de fundo claro e não preto. Alguém sabe o que há de errado com isso? Qualquer sugestão apreciada.

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

RESOLVIDO : Corrigi os problemas. Está funcionando tão bem para iPhone e iPad. Controlador de vista modal sem fundo preto apenas clearColor / transparente. A única coisa que eu preciso para a mudança é Troquei UIModalPresentationFullScreena UIModalPresentationCurrentContext. Quão simples é isso!

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

AVISO: Se você estiver usando uma modalPresentationStylepropriedade de 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];

AVISO: A má notícia é que a solução acima não funciona no iOS 7. A boa notícia é que eu corrigi o problema no iOS7! Pedi ajuda a alguém e aqui está o que ele disse:

Ao apresentar um controlador de exibição modalmente, o iOS remove os controladores de exibição abaixo da hierarquia de visualizações pela duração em que é apresentado. Embora a visualização do seu controlador de exibição apresentado de forma modal seja transparente, não há nada abaixo dele, exceto a janela do aplicativo, que é preta. O iOS 7 introduziu um novo estilo de apresentação modal UIModalPresentationCustom, que faz com que o iOS não remova as visualizações abaixo do controlador de visualização apresentado. No entanto, para usar esse estilo de apresentação modal, você deve fornecer seu próprio delegado de transição para lidar com a apresentação e dispensar animações. Isso está descrito na palestra 'Transições personalizadas usando controladores de exibição' da WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, que também aborda como implementar seu próprio delegado de transição.

Você pode ver minha solução para o problema acima no iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

alta tecnologia
fonte
1
certifique-se de definir o modalPresentationStyle do rootViewController, caso contrário, ele não funcionará.
Thorsten
Por favor, dê uma olhada no comentário sobre esta resposta stackoverflow.com/a/25990081/1418457 , ele funciona
onmyway133
Este stackoverflow.com/q/27598846/1603234 me fazer sorrir, agora a sua vez :)
Hemang
Eu tive que fazer self.modalPresentationStyle = UIModalPresentationCurrentContext; com o controlador de exibição apresentado para fazê-lo funcionar, não com o controlador de apresentação.
Tulleb 29/08/2015
1
Verifique a resposta de Brody abaixo. modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; vai resolver o problema,
GoodSp33d

Respostas:

143

iOS8 +

No iOS8 +, agora você pode usar o novo modalPresentationStyle UIModalPresentationOverCurrentContext para apresentar um controlador de exibição com um plano de fundo transparente:

MyModalViewController *modalViewController = [[MyModalViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;           
[self presentViewController:modalViewController animated:YES completion:nil];    
Brody Robertson
fonte
5
Deve ser a resposta aceita. A resposta anteriormente aceita ainda é válida por motivos herdados, mas esse é o método recomendado.
Tomasz Bąk
3
Se você está desenvolvendo apenas para o iOS 8, siga esta resposta! Funciona
Mário Carvalho
2
Isso é bom, mas não deveria ser a última linha [self presentViewController:modalViewController animated:YES completion:nil];? (em vez de targetController)?
SuperDuperTango
3
A fim de resolver isso para mim eu adicionei modalViewController.view.backgroundColor = UIColor.clearColor () graças para a solução
Pramod
alguém pode me fornecer o código para pushviewcontroller também (quero dizer para controlador de navegação).
Alok
140

RESOLVIDO : Corrigi os problemas. Está funcionando tão bem para iPhone e iPad. Controlador de vista modal sem fundo preto apenas clearColor / transparente. A única coisa que preciso alterar é a substituição de UIModalPresentationFullScreen por UIModalPresentationCurrentContext. Quão simples é isso!

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

AVISO: Se você estiver usando uma propriedade modalPresentationStyle de 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];

AVISO: A má notícia é que a solução acima não funciona no iOS 7. A boa notícia é que eu corrigi o problema no iOS7! Pedi ajuda a alguém e aqui está o que ele disse:

Ao apresentar um controlador de exibição modalmente, o iOS remove os controladores de exibição abaixo da hierarquia de visualizações pela duração em que é apresentado. Embora a visualização do seu controlador de exibição apresentado de forma modal seja transparente, não há nada abaixo dele, exceto a janela do aplicativo, que é preta. O iOS 7 introduziu um novo estilo de apresentação modal, UIModalPresentationCustom, que faz com que o iOS não remova as visualizações abaixo do controlador de visualização apresentado. No entanto, para usar esse estilo de apresentação modal, você deve fornecer seu próprio delegado de transição para lidar com a apresentação e dispensar animações. Isso está descrito na palestra 'Transições personalizadas usando controladores de exibição' da WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218, que também aborda como implementar seu próprio delegado de transição.

Você pode ver minha solução para o problema acima no iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

alta tecnologia
fonte
1
self.modalPresentationStyle = UIModalPresentationCurrentContext;fez isso.
Adriano Lucas
4
btw .. Eu observei isso por causa de self.modalPresentationStyle = UIModalPresentationCurrentContext; ele não está apresentando modalViewController com animação .. alguma idéia?
Devarshi
1
@Miraaj seguida, definindo modalPresentationStyle volta para UIModalPresentationFullScreen antes de mostrar UIViewController deve funcionarself.modalPresentationStyle = UIModalPresentationFullScreen; [self performSegueWithIdentifier:@"CustomSegue" sender:self];
hightech
1
Executando isso no iOS 6 e 7, o novo controlador de exibição fica claro ao animar a apresentação, mas uma vez instalado, o fundo fica preto. Fica claro novamente ao animar a demissão. Alguém mais teve esse problema?
Drew C
3
@pkamb Atualizei a solução para iOS 7. stackoverflow.com/a/11252969/1344459 Espero que ajude você.
hightech
114

Portanto, para pensadores puramente visuais e fãs de storyboard, você pode:

1. Apresentando o View Controller

Definir contexto

2. Controlador de exibição apresentado

Apresentação: Contexto Atual

pasevin
fonte
Essa deve ser a resposta aceita. Isso é tudo o que você precisa fazer para que isso funcione e, em seguida, defina a cor de plano de fundo da exibição no controlador modal.
Jesse
Concordado, as opções do storyboard substituem o código nesse caso.
C0D3
17
Esta resposta é tão doce que agora tenho diabetes.
GeneCode 10/10
25

Solução Swift 3 e 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)
Kevin ABRIOUX
fonte
16

Este é do xCode 7 beta 4 usando um arraste de controle segue. Simplesmente defina o plano de fundo do seu destino para limpar e defina as propriedades de segue no IB como esta (Nota: a apresentação também pode ser "Em tela cheia"):

insira a descrição da imagem aqui

smileBot
fonte
2
OBRIGADO. Eu fiz o seu segue fix + a resposta do ViewControllers por @pasevin e funcionou !!
CSawy
1
Isso respondeu à minha pergunta. Muito obrigado. Tenho um voto
positivo
8

Achei que a maneira mais fácil de fazê-lo funcionar no iOS7 e iOS8 é adicionar set the presentationStyle a UIModalPresentationOverCurrentContext no modallyPresentedVC (ViewController que você deseja apresentar modalmente) por causa do iOS8:

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

e UIModalPresentationCurrentContext na apresentação de CV (o controlador que apresenta o modallyPresented) devido ao iOS7:

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

Porque as coisas são tratadas de maneira diferente no iOS7 e iOS8. É claro que você não precisa definir as propriedades navigationController se não estiver usando uma. Espero que ajude.

3vangelos
fonte
salvou meu bacon! Obrigado
Duck
5

Versão 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)
Mojtabye
fonte
4

Outra maneira (não há necessidade de criar transição personalizada e funciona no iOS 7)

Usando o Storyboard:

Crie o Child View Controller com tamanho de liberdade, defina a largura da visualização como 500x500 (por exemplo) e adicione o próximo método:

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

Em seguida, crie um Modal segue com Form Sheet e teste-o.

educaPix
fonte
Você é incrível!!! isso realmente funciona !!! (definir o tamanho da "liberdade" no IB não afeta o valor da anithing, é uma métrica simulada, mas, de qualquer maneira, funciona !!!) e é muito simples !!!
Radu Simionescu 28/01
4

Solução iOS 7 com segue personalizado:

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

Solução baseada em código de alta tecnologia.

Max Gribov
fonte
Quando eu rejeito o by [self dispensViewViewControllerAnimated: YES conclusão: NULL]; Eu recebo uma exceção ??
Asadullah Ali
Sim para este código. Ou você precisa implementar o método animationControllerForDismissedController para a animação começar a funcionar.
Max Gribov
4

Para mim, isso funciona:

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

MMPushNotificationViewControlleré o controlador do Transparent View e também fiz a MMPushNotificationViewControllercor do modo de exibição como clearcolor. Agora, tudo o que eu fiz e fiz meu controlador Transparentview.

Manab Kumar Mal
fonte
2

Para iOS7

Agora existe uma maneira de conseguir isso usando as transições personalizadas do iOS7, da seguinte maneira:

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

Para criar sua transição personalizada, você precisa de duas coisas:

  • Um objeto TransitionDelegate (implementando <UIViewControllerTransitionDelegate>)
  • Um objeto "AnimatedTransitioning" (implementando <UIViewControllerAnimatedTransitioning>)

Você pode encontrar mais informações sobre transições personalizadas neste tutorial .

Kirualex
fonte
Quaisquer razões específicas pelas quais você adicionou mainviewcontroller e segunda classe de controlador de exibição na classe animador? por que você não usou diretamente UIViewController * toVC = (UIViewController *) [transiçãoContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [transiçãoContext viewControllerForKey: UITransitionContextFromViewControllerKey];
Satyam Raikar 28/02
Não é o meu tutorial, por isso não conheço bem os detalhes. Seu ponto parece válido embora.
Kirualex 28/02
2

Funciona muito bem no iOS7 e 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];
hoppus
fonte
Uma duplicata da segunda melhor resposta.
Tomasz Bąk
2

Você também pode 'adicionar novamente' a janela à exibição.

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

E dessa maneira, a apresentação pode ser animada.

Elf Sundae
fonte
1

Para o iOS 7 e apenas usando o Interface Builder, isso pode ser feito configurando a Apresentação como "Over Current Context" em todos os controladores de exibição envolvidos na apresentação modal. Mesmo para controladores de navegação.

Por exemplo, defina-o em todos esses controladores de exibição:

NavController -> RootViewController -> ModalViewController

insira a descrição da imagem aqui

David Hernandez
fonte
0

Eu não brinquei muito com o construtor Storyboard / Interface, mas o que me impressiona é que você está dizendo que a vista tem uma cor clara (ou seja, 100% alfa / transparente) e também está dizendo que ela é opaca ( 0% alfa - completamente sólido). Essas duas coisas não parecem se encaixar. Gostaria de comentar a self.view.opaque = YES;linha e ver se funciona;)

Ah, outra coisa que eu pensei - é perfeitamente possível que o seu controlador de exibição tenha o fundo alfa, mas é claro que o alfa estará mostrando a cor da janela base ou do controlador de visualização raiz do programa, que é por preto padrão. A camada básica de todo o aplicativo não pode ter um plano de fundo transparente - transparente para quê? O que há por trás disso? Tem que haver algo para ver através da transparência. Isso faz sentido?

WendiKidd
fonte
Tentei comentar o self.view.opaque = YES; linha e não funciona. :-(
hightech 28/06
Você leu a segunda parte da minha resposta? Talvez você não consiga fazer o que deseja, dependendo da configuração. O que você está colocando por trás do clearColor VC? Talvez possamos resolver isso ^^
WendiKidd
-3

Basta usar "self.modalPresentationStyle = UIModalPresentationCurrentContext;", na exibição de apresentação

Vai funcionar bem :)

Venkateswarlu.NP
fonte
1
Isso está apenas repetindo o que as respostas existentes já disseram.
Pang