Mostrar clearColor UIViewController sobre UIViewController

150

Tengo una UIViewControllervista como una subvista / modal encima de otra UIViewControllervista, como que la subvista / modal debe ser transparente y cualquier componente que se agregue a la subvista debe ser visible. El problema es que lo que tengo es que la subvista muestra un fondo negro en lugar de tener clearColor. Estoy tratando de hacer UIViewque el fondo sea un color claro y no negro. ¿Alguien sabe qué tiene de malo? Cualquier sugerencia 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];
}

RESUELTO : Solucioné los problemas. Funciona muy bien tanto para iPhone como para iPad. Controlador de vista modal sin fondo negro solo claro Color / transparente. Lo único que necesito es el cambio que sustituye UIModalPresentationFullScreena UIModalPresentationCurrentContext. ¡Qué simple es eso!

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: si está utilizando una modalPresentationStylepropiedad 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: La mala noticia es que la solución anterior no funciona en iOS 7. ¡La buena noticia es que solucioné el problema para iOS7! Le pedí ayuda a alguien y esto es lo que dijo:

Al presentar un controlador de vista modalmente, iOS elimina los controladores de vista debajo de la jerarquía de vista durante el tiempo que se presenta. Si bien la vista de su controlador de vista presentado modalmente es transparente, no hay nada debajo, excepto la ventana de la aplicación, que es negra. iOS 7 introdujo un nuevo estilo de presentación modal UIModalPresentationCustom, que hace que iOS no elimine las vistas debajo del controlador de vista presentado. Sin embargo, para usar este estilo de presentación modal, debe proporcionar su propio delegado de transición para manejar la presentación y descartar las animaciones. Esto se describe en la charla 'Transiciones personalizadas utilizando controladores de vista' de WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218 que también cubre cómo implementar su propio delegado de transición.

Puede ver mi solución para el problema anterior en iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

alta tecnología
fuente
1
asegúrese de establecer el modalPresentationStyle del rootViewController, de lo contrario no funcionará
Thorsten
Por favor, eche un vistazo al comentario en esta respuesta stackoverflow.com/a/25990081/1418457 , funciona
onmyway133
Este stackoverflow.com/q/27598846/1603234 me hace sonreír, ahora es tu turno :)
Hemang
Tuve que hacer self.modalPresentationStyle = UIModalPresentationCurrentContext; con el controlador de vista presentado para que funcione, no con el presentador.
Tulleb
1
Verifique la respuesta de Brody a continuación. modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; va a resolver el problema,
GoodSp33d

Respuestas:

143

iOS8 +

En iOS8 + ahora puede usar el nuevo modalPresentationStyle UIModalPresentationOverCurrentContext para presentar un controlador de vista con un fondo transparente:

MyModalViewController *modalViewController = [[MyModalViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;           
[self presentViewController:modalViewController animated:YES completion:nil];    
Brody Robertson
fuente
55
Debería ser la respuesta aceptada. La respuesta previamente aceptada sigue siendo válida por razones antiguas, pero este es el método recomendado.
Tomasz Bąk
3
Si está desarrollando solo para ios 8, ¡vaya con esta respuesta! Funciona
Mário Carvalho
2
Esto es bueno, pero ¿no debería ser la última línea [self presentViewController:modalViewController animated:YES completion:nil];? (en lugar de targetController)?
SuperDuperTango
3
Para que esto funcione para mí, agregué modalViewController.view.backgroundColor = UIColor.clearColor () gracias por la solución
Pramod
¿Alguien puede proporcionarme el código para pushviewcontroller también (quiero decir para el controlador de navegación).
Alok
140

RESUELTO : Solucioné los problemas. Funciona muy bien tanto para iPhone como para iPad. Controlador de vista modal sin fondo negro solo claro Color / transparente. Lo único que necesito cambiar es que reemplacé UIModalPresentationFullScreen por UIModalPresentationCurrentContext. ¡Qué simple es eso!

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: si está utilizando una propiedad 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: La mala noticia es que la solución anterior no funciona en iOS 7. ¡La buena noticia es que solucioné el problema para iOS7! Le pedí ayuda a alguien y esto es lo que dijo:

Al presentar un controlador de vista modalmente, iOS elimina los controladores de vista debajo de la jerarquía de vista durante el tiempo que se presenta. Si bien la vista de su controlador de vista presentado modalmente es transparente, no hay nada debajo, excepto la ventana de la aplicación, que es negra. iOS 7 introdujo un nuevo estilo de presentación modal, UIModalPresentationCustom, que hace que iOS no elimine las vistas debajo del controlador de vista presentado. Sin embargo, para usar este estilo de presentación modal, debe proporcionar su propio delegado de transición para manejar la presentación y descartar las animaciones. Esto se describe en la charla 'Transiciones personalizadas utilizando controladores de vista' de WWDC 2013 https://developer.apple.com/wwdc/videos/?id=218 que también cubre cómo implementar su propio delegado de transición.

Puede ver mi solución para el problema anterior en iOS7: https://github.com/hightech/iOS-7-Custom-ModalViewController-Transitions

alta tecnología
fuente
1
self.modalPresentationStyle = UIModalPresentationCurrentContext;lo hizo.
Adriano Lucas
44
por cierto ... lo he observado por self.modalPresentationStyle = UIModalPresentationCurrentContext; no presenta modalViewController con animación ... alguna idea?
Devarshi
1
@Miraaj Luego configura modalPresentationStyle de nuevo en UIModalPresentationFullScreen antes de mostrar que UIViewController debería funcionarself.modalPresentationStyle = UIModalPresentationFullScreen; [self performSegueWithIdentifier:@"CustomSegue" sender:self];
hightech
1
Al ejecutar esto en iOS 6 y 7, el nuevo controlador de vista es claro mientras anima la presentación, pero una vez que está en su lugar, el fondo se vuelve negro. Se vuelve claro nuevamente al animar el despido. ¿Alguien más ha tenido este problema?
Drew C
3
@pkamb Actualicé la solución para iOS 7. stackoverflow.com/a/11252969/1344459 Espero que les sirva de ayuda.
hightech
114

Entonces, para los pensadores puramente visuales y los fanáticos del guión gráfico, puedes hacer:

1. Presentación del controlador de vista

Definir contexto

2. Controlador de vista presentado

Presentación: sobre el contexto actual

pasevin
fuente
Esta debería ser la respuesta aceptada. Esto es todo lo que tiene que hacer para que esto funcione, luego configure el color de fondo de la vista en el controlador modal para borrar.
Jesse
De acuerdo, las opciones del guión gráfico sobrescriben el código en este caso.
C0D3
17
Esta respuesta es tan dulce que ahora tengo diabetes.
GeneCode
25

Solución Swift 3 y 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
fuente
16

Esto es de xCode 7 beta 4 usando un control de arrastre segue. Simplemente configure el fondo de su destino para que se borre y configure las propiedades de segue en IB de la siguiente manera (nb. La presentación también puede ser "Sobre pantalla completa"):

ingrese la descripción de la imagen aquí

smileBot
fuente
2
GRACIAS. Hice su solución segue + ¡la respuesta de ViewControllers de @pasevin y funcionó!
CSawy
1
Esto respondió mi pregunta. Muchas gracias. Tener un voto
positivo
8

Encontré que la forma más fácil de hacer que funcione en iOS7 e iOS8 es agregar set the presentationStyle a UIModalPresentationOverCurrentContext en el modallyPresentedVC (ViewController que desea presentar modalmente) debido a iOS8:

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

y UIModalPresentationCurrentContext en presentVC (el controlador que presenta modallyPresented) debido a iOS7:

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

Porque las cosas se manejan de manera diferente en iOS7 y iOS8. Por supuesto, no tiene que establecer las propiedades de navigationController si no está usando una. Espero que ayude.

3vangelos
fuente
salvó mi tocino! Gracias
Duck
5

Versión 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
fuente
4

Otra forma (no es necesario crear una transición personalizada y funciona en iOS 7)

Usando Storyboard:

Cree el controlador de vista infantil con tamaño de libertad, establezca el ancho de vista en 500x500 (por ejemplo) y agregue el siguiente método:

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

Luego, cree una secuencia modal con la hoja de formulario y pruébela.

educaPix
fuente
¡¡¡Eres fabuloso!!! esto realmente funciona! (¡establecer el tamaño de "libertad" en IB no afecta a nada, es una métrica simulada, pero de todos modos, funciona!) y es tan simple !!!
Radu Simionescu
4

Solución iOS 7 con 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

Solución basada en código de alta tecnología.

Max Gribov
fuente
Cuando descarto el by [self -sheadViewViewControllerAnimated: YES complete: NULL]; ¿Tengo una excepción?
Asadullah Ali
Sí para este código. O debe implementar el método animationControllerForDismissedController para que la animación comience a funcionar.
Max Gribov
4

Para mí esto 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];

MMPushNotificationViewControlleres el controlador de Vista Transparente y también he creado el MMPushNotificationViewControllercolor de la vista como color claro. Ahora todo lo que he hecho e hice mi controlador Transparentview.

Manab Kumar Mal
fuente
2

Para iOS7

Ahora hay una manera de lograr esto usando las transiciones personalizadas de iOS7, de esta manera:

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

Para crear su transición personalizada, necesita 2 cosas:

  • Un objeto TransitionDelegate (implementando <UIViewControllerTransitionDelegate>)
  • Un objeto "AnimatedTransition" (implementación <UIViewControllerAnimatedTransitioning>)

Puede encontrar más información sobre transiciones personalizadas en este tutorial .

Kirualex
fuente
¿Alguna razón específica por la que ha agregado la clase mainviewcontroller y la segunda vista del controlador en la clase animator? ¿por qué no usaste directamente UIViewController * toVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextToViewControllerKey]; UIViewController * fromVC = (UIViewController *) [transitionContext viewControllerForKey: UITransitionContextFromViewControllerKey];
Satyam Raikar
No es mi tutorial, así que no conozco los entresijos de esto. Sin embargo, su punto parece válido.
Kirualex
2

Funciona muy bien en iOS7 y 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
fuente
Un duplicado de la segunda mejor respuesta.
Tomasz Bąk
2

También puede "volver a agregar" la ventana a la vista.

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

Y de esta manera, la presentación puede ser animada.

Elf Sundae
fuente
1

Para iOS 7 y solo mediante el uso de Interface Builder, se puede lograr configurando la Presentación en "Contexto actual" en todos los controladores de vista involucrados en la presentación modal. Incluso para los controladores de navegación.

Por ejemplo, configúrelo en todos estos controladores de vista:

NavController -> RootViewController -> ModalViewController

ingrese la descripción de la imagen aquí

David Hernández
fuente
0

No he jugado mucho con Storyboard / Interface Builder, pero lo que me llama la atención es que le estás diciendo a la vista que sea de color claro (es decir, 100% alfa / transparente) y también que sea opaca ( 0% alfa - completamente sólido). Estas dos cosas no parecen encajar. Yo comentaría la self.view.opaque = YES;línea y vería si funciona entonces;)

Ah, algo más en lo que acabo de pensar: es completamente posible que su controlador de vista TENGA el fondo alfa, pero, por supuesto, el alfa se mostrará a través del color de la ventana base o del controlador de vista raíz del programa, que es por negro predeterminado La capa base de toda su aplicación no puede tener un fondo transparente, ¿transparente para qué? ¿Qué hay detrás? Tiene que haber algo que ver A TRAVÉS de la transparencia. ¿Tiene sentido?

WendiKidd
fuente
Traté de comentar el self.view.opaque = YES; línea y no funciona. :-(
alta tecnología
¿Leíste la segunda parte de mi respuesta? Es posible que no pueda hacer lo que quiera, dependiendo de su configuración. ¿Qué está colocando detrás del clearColor VC? Tal vez podamos solucionar esto ^^
WendiKidd
-3

Simplemente use "self.modalPresentationStyle = UIModalPresentationCurrentContext;", en la vista de presentación

Funcionará bien :)

Venkateswarlu.NP
fuente
1
Esto es solo repetir lo que las respuestas existentes ya han dicho.
Pang