2012-01-08 23 views
27

Para hacer un UIView en la parte superior de todas las vistas como el comportamiento de UIAlertView, la mejor manera que veo es poniéndolo en la ventana de la aplicación, que es mediante la adición de la ver para:Ver en la parte superior de todo: UIWindow subvista VS UIViewController subvista

[[[UIApplication sharedApplication] delegate] window] 

Sin embargo, la desventaja que encontré es que no toma automáticamente la rotación. Para que funcione en rotación, la mejor manera de hacerlo es agregar la vista en el AppDelegate actual window.navigationController/rootViewController, sin embargo, al hacerlo, ya no estará encima de todo. Supongamos que cuando se muestra la vista y hay una ventana emergente modalViewController, la vista modal ciertamente cubrirá la vista.

Mi pregunta es, ¿es posible agregar una subvista a la ventana más alta y orientación de soporte? ¿Necesito dos juegos de archivos Nib en este caso? ¿Cómo combina UIAlertView la magia para combinar el soporte de orientación más alto &? Cuando miro en el UIAlertView.h, veo que en realidad hay 2 UIWindows, una vez que se llama originalWindow y otra llamada dimWindow. ¿Hay algún lugar donde pueda encontrar el código fuente para UIAlertView.m?

Respuesta

4

Solo se muestra la primera subvista de UIWindow sobre los cambios de orientación. (< iOS8)

Su pregunta es muy similar a éste:

Multiple views in a UIWindow

Como la respuesta no dice, puede registrarse para recibir notificaciones de cambios de orientación y manejar con la redistribución de la 'encima' subvista de esa manera.

+1

¿Cómo registrar la vista en el dispositivo para recibir un evento de rotación? No es View Controller, por lo que no hay funciones de delegado para él. ¿Debo atrapar UIDeviceOrientationDidChangeNotification para cambiar a la orientación correspondiente? –

2

Aquí hay una posible solución, lo estoy explicando en unos pocos pasos.

  1. inicio Con una clase UIViewController heredado en lugar de UIView, digamos clase llamada TopViewController heredado por UIViewController
  2. Ya que no se puede registrar la rotación del dispositivo/interfaz de UIView heredó clase, la clase TopViewController que se hereda de UIViewController tiene métodos que responden a View Rotation Events. Los eventos de rotación se pueden capturar ahora.
  3. Por fin puedes poner la vista TopViewController en la parte superior de UIWindow usando el mismo método que mencionaste en tu pregunta.

    [[[[UIApplication sharedApplication] delegate] window] addSubview:(TopViewController object).view]; 
    

Espero que esto ayude.

+0

La propiedad de vista de UIViewController tampoco rotará. Desafortunadamente. https://developer.apple.com/library/ios/qa/qa1688/_index.html – khunshan

15

La mejor solución que he encontrado es crear una vista de contenedor transparente, agregar ese contenedor a la ventana y colocar su alerta dentro del contenedor. A continuación, puede registrarse para UIApplicationWillChangeStatusBarOrientationNotification para recibir eventos de rotación y transformar el contenedor; esto le permite manipular de forma independiente del marco de la alerta:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    ... 
    self.container = [[UIView alloc] initWithFrame:self.window.bounds]; 
    [self.container addSubview:self.alertView]; 
    [self.window addSubview:self.container]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(statusBarWillRotate:) 
                name:UIApplicationWillChangeStatusBarOrientationNotification 
               object:nil]; 
    ... 
} 
... 
- (void)statusBarWillRotate:(NSNotification *)theNotification 
{ 
    CGFloat rotation = 0; 
    switch ([notification[UIApplicationStatusBarOrientationUserInfoKey] intValue]) 
    { 
     case UIInterfaceOrientationLandscapeLeft: 
      rotation = -M_PI_2; 
      break; 
     case UIInterfaceOrientationLandscapeRight: 
      rotation = M_PI_2; 
      break; 
     case UIInterfaceOrientationPortraitUpsideDown: 
      rotation = M_PI; 
      break; 
     case UIInterfaceOrientationPortrait: 
     default: 
      rotation = 0; 
      break; 
    } 
    CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(rotation); 
    CGSize rotatedSize = CGRectApplyAffineTransform(self.window.bounds, rotationTransform).size; 
    [UIView animationWithDuration:[UIApplication sharedApplication].statusBarOrientationAnimationDuration 
         animations:^{ 
     self.container.transform = rotationTransform; 
     // Transform invalidates the frame, so use bounds/center 
     self.container.bounds = CGRectMake(0, 0, rotatedSize.width, rotatedSize.height); 
     self.container.center = CGPointMake(self.window.bounds.size.width/2, self.window.bounds.size.height/2); 
    }]; 
} 

Usted puede, si realmente desea, crear una ventana completamente nueva con su windowLevel propiedad establecida en UIWindowLevelAlert, lo que garantizará que la ventana permanezca por encima de todos los demás vistas, incluido el teclado, pero la gestión de ventanas se vuelve un poco complicado.La solución anterior debería ser suficiente para la mayoría de las necesidades.

El problema con la simple adición de vista de un controlador de vista de una ventana es que no se garantiza que recibirá toda la rotación y view[Will|Did][Disa|A]ppear: mensajes a menos que se añade al controlador de vista jerarquía través addChildViewController: en el controlador de vista raíz.

+0

Tengo un problema con esta solución. No puedo registrar toques en esa vista superior del contenedor. UIButtons no funciona, por ejemplo. – asendra

+0

@asendra Parece que su ventana no es la ventana clave, pero es posible que desee publicar su propia pregunta con más detalles. – Austin

Cuestiones relacionadas