5

Quiero mostrar un modal UIViewController con un marco personalizado en iPad, centrado en la parte superior de su controlador de vista principal.Mostrar el controlador de vista modal con marco personalizado en el iPad

He intentado utilizar una hoja de formulario pero, hasta donde sé, el marco y el efecto de sombra no pueden modificarse.

vc.modalPresentationStyle = UIModalPresentationFormSheet; 
[self presentModalViewController:cv animated:YES]; 

También he intentado usar un popover pero por lo que yo sé bien que no se puede centrar o no puede ocultar la flecha.

¿Hay alguna otra forma de mostrar los controladores de vista modal? ¿Es posible resolver este problema usando hojas de formulario o elementos emergentes?

+1

Puede mostrar un popover donde lo desee utilizando presentPopoverFromRect e incluso hacerlo comportarse modalmente, pero el único inconveniente es que no hay forma de ocultar la flecha. – Anna

Respuesta

4

No hay manera oficial a hacer esto sin embargo se puede obtener el comportamiento deseado por escrito una vista personalizada que mantiene una referencia o un delegado para interactuar con su controlador de vista de presentación y de añadir a la jerarquía de vistas. Para realmente obtener la sensación modal, también puede colocar una superposición transparente sobre el controlador de presentación justo debajo de su vista 'modal'. Lo he hecho en varias aplicaciones y generalmente funciona muy bien. Es probable que necesite hacer una vista de superposición personalizada para que pueda interceptar toques y animar más elegantemente su presentación.

Mi superposición transparente suele ser algo como esto:

@protocol TransparentOverlayDelegate <NSObject> 

@optional 
- (void)transparentOverlayWillDismiss:(TransparentOverlay *)backgroundTouch; 
- (void)transparentOverlayDidDismiss:(TransparentOverlay *)backgroundTouch; 
@end 


@interface TransparentOverlay : UIView { 

    id<TransparentOverlayDelegate> _delegate; 
    UIView *_contentView; 
    CGFloat _pAlpha; 
} 

@property(nonatomic, assign) id<TransparentOverlayDelegate> delegate; 
@property(nonatomic, retain) UIView *contentView; 
@property(nonatomic, assign) CGFloat pAlpha; 

- (void)presentTransparentOverlayInView:(UIView *)view; 
- (void)dismissTransparentOverlay:(BOOL)animated; 

Mi punto de vista modal costumbre es generalmente algo como esto:

@protocol ModalViewDelegate <NSObject> 
- (void)performSelectorOnDelegate:(SEL)selector; 
@end 

@interface ModalView : UIView { 
    id<ModalViewDelegate> _delegate; 
} 

@property(nonatomic, assign) id<ModalViewDelegate> delegate; 

En mi controlador de vista presentando lo general se haga lo siguiente:

- (void)presentModalController { 
    TransparentOverlay *to = [[[TransparentOverlay alloc] initWithFrame:self.view.bounds] autorelease]; 
    to.delegate = self; 

    ModalView *mv = [[ModalView alloc] initWithFrame:CGRectMake(500, 500, 300, 300)]; 
    mv.delegate = self; 

    to.contentView = mv; 
    [mv release]; 

    [to presentTransparentOverlayInView:self.view]; 
} 

Uso de los delegados definidos en las dos clases me da acceso bastante abierto para manipular mi controlador de presentación, así como mi presentación y despedida, según lo deseado. La única desventaja de esto es cuando se usa en una vista con una NavigationBar, ya que los límites de la vista del controlador que presenta no contendrán los límites de la NavigationBar, dejándola abierta para la interacción, hay formas de evitar esto, pero no de ellos. son muy bonitos (agregar una vista a la vista del controlador de navegación es una opción).

+0

¿Cuál es el propósito de '- (void) performSelectorOnDelegate: (SEL) selector;' en el 'ModalViewDelegate'? –

1

Esto puede no responder totalmente a su pregunta. Pero llamo al siguiente código desde un elemento de botón derecho en un controlador de navegación que coloqué previamente en la parte superior de una vista de detalle de un controlador splitviewcontroller.

Esta vista modal cubre toda la pantalla. ¿Quería cubrir, por ejemplo, la vista de detalles solo si se llama en el control de vista detallada?

- (void)aboutAction { 

About *about = [[About alloc] init]; 
UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:about]; 
[about release]; 
nav1.navigationBar.barStyle = UIBarStyleBlackOpaque; 
nav1.modalPresentationStyle = UIModalPresentationFullScreen; 
nav1.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; 
[self presentModalViewController:nav1 animated:YES ]; 
[nav1 release]; 

} 
6

Estoy usando el siguiente método para crear un controlador de vista modal con cualquier tamaño dado centrado en la pantalla. Puede cambiarlo al centro en el controlador de vista principal si lo desea. Esto funciona desde el guión gráfico para que pueda enviar el controlador de vista como un argumento en su lugar. Pero aparte de eso, hace lo que necesita.

NOTA: He encontrado que si intenta mostrar otro modal sobre este, volverá al tamaño original.

- (UIViewController *) presentModalViewControllerWithIdentifier:(NSString *)identifier 
                 andSize:(CGSize)size 
             andModalTransitionStyle:(UIModalTransitionStyle)modalTransitionStyle { 
    UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier]; 


    viewController.modalPresentationStyle = UIModalPresentationPageSheet; 
    viewController.modalTransitionStyle = modalTransitionStyle; 
    [self presentModalViewController:viewController animated:YES]; 
    viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin | 
    UIViewAutoresizingFlexibleLeftMargin | 
    UIViewAutoresizingFlexibleRightMargin;  
    CGRect screenBounds = [[UIScreen mainScreen] bounds]; 
    viewController.view.superview.frame = CGRectMake(0, 0, size.width, size.height); 
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds), CGRectGetMidY(screenBounds)); 
    viewController.view.superview.center = UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? center : CGPointMake(center.y, center.x); 

    return viewController; 
} 

Si se trata de la única cosa que quiere que trabaja muy bien. Pero lo que he encontrado es que la implementación de controladores de vista modal de Apple es un poco contraproducente ya que no se puede acceder a ninguna de sus partes subyacentes y por lo tanto no se puede animar por completo. Útil si quieres tener tus propias transiciones.

Y no cae también en la categoría de un controlador de vista infantil ya que se encuentra sobre todas las otras vistas en la ventana.

+0

Esto me ayudó mucho. Gracias. –

+0

+1 Estaba intentando cambiar el tamaño de los modales durante años, pero ninguna de las soluciones de StackOverflow fue útil. Tampoco redimensionó/​​centró la Vista correctamente o no funcionó con todos los estilos de transición. ¡Esta solución es PERFECTA! –

+0

IOS 7 Actualice a continuación y podría eliminar el problema vc engendrado hijo mencionado anteriormente – gjpc

1

prefiero la respuesta de Fabio-Oliveira pero requiere algunos ajustes para permitir que funcione en el ambiente rosca de varias de IOS 7:

- (UIViewController *)presentModalViewControllerWithId:(NSString *)identifier 
              andSize:(CGSize)size 
          andModalTransitionStyle:(UIModalTransitionStyle)style 
{ 
    UIViewController *viewController = 
      [self.storyboard instantiateViewControllerWithIdentifier:identifier]; 

    viewController.modalPresentationStyle = UIModalPresentationPageSheet; 
    viewController.modalTransitionStyle = style; 

    [self presentViewController:viewController animated:YES completion:nil]; 

    viewController.view.superview.autoresizingMask = 
     UIViewAutoresizingFlexibleTopMargin | 
     UIViewAutoresizingFlexibleBottomMargin | 
     UIViewAutoresizingFlexibleLeftMargin | 
     UIViewAutoresizingFlexibleRightMargin; 

    viewController.view.superview.frame = 
        CGRectMake(0, 0, size.width, size.height); 

    return viewController; 
} 

Ahora coloque el código centrado en el objetivo de VC por lo que el nuevo hilo hace el trabajo :

- (void)viewWillLayoutSubviews 
{ 
    [super viewWillLayoutSubviews]; 
    CGRect screenBounds = [[UIScreen mainScreen] bounds]; 
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds), 
           CGRectGetMidY(screenBounds)); 

    self.view.superview.center = 
    UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? 
             center : CGPointMake(center.y, center.x); 
} 

Oh Sí, si usted está apoyando a aquellos preciosa iOS 5 iPad 1 de, asegúrese de dejar que la rotación vc objetivo:

- (BOOL)shouldAutorotateToInterfaceOrientation: 
         (UIInterfaceOrientation)interfaceOrientation 
{ 
    return YES; 
} 
+0

Hola @gjpc, utilicé tu código y funciona bien, pero cuando aparece, me refiero a cuando se presenta el modalView, se abre desde la esquina y se desvía hacia el centro. Encontraste esto. – Ranjit

+0

@Ranjit Yo uso andModalTransitionStyle: UIModalTransitionStyleCoverVertical]; y aparecen desde la parte inferior y salen por la parte inferior – gjpc

+0

He intentado usar ModalTransitionStyle: UIModalTransitionStyleCoverVertical] ;, pero el modal aparece desde la esquina inferior y cuando lo descarto lo descarta en el centro de la parte inferior. – Ranjit

1

En mi caso, anulando viewWillLayoutSubviews hizo el truco.

- (void)viewWillLayoutSubviews { 
     [super viewWillLayoutSubviews]; 

    self.view.superview.frame = CGRectMake(100.f, 100.f, <width>, <height>); 
} 

Nada se necesitaba más para cambiar la posición y límites de ModalViewController.

+0

Esto funcionó para mí, hasta que la actividad del usuario trajo el teclado del iPad en pantalla y en ese momento el modal volvió a su posición anterior. –

Cuestiones relacionadas