2012-01-08 18 views
27

Per rendere un UIView in cima a tutte le visualizzazioni come il comportamento di UIAlertView, il modo migliore che vedo è inserendolo nella finestra dell'app, che è aggiungendo il visualizzabile su:Vedi sopra tutto: sottoview UIWindow VS subview UIViewController

[[[UIApplication sharedApplication] delegate] window] 

Tuttavia, il lato negativo che ho rilevato è che non si attiva automaticamente in rotazione. Per fare in modo che giri a rotazione, il modo migliore per farlo è aggiungere la vista su AppDelegate attuale window.navigationController/rootViewController, tuttavia, facendo ciò, non sarà più al di sopra di tutto. Diciamo che quando la vista è visualizzata e c'è un popup modalViewController, la vista modale coprirà sicuramente la vista.

La mia domanda è, è possibile aggiungere sottomenu nella parte superiore della finestra più e orientamento di supporto? Ho bisogno di due set di file Nib in questo caso? In che modo UIAlertView combina il massimo supporto di orientamento &? Quando guardo nello UIAlertView.h, vedo che c'è in realtà 2 UIWindows, una volta è chiamato originalWindow e un altro chiamato dimWindow. C'è un posto dove posso trovare il codice sorgente per UIAlertView.m?

risposta

4

Solo la prima sottoview di UIWindow viene informata sui cambiamenti di orientamento. (< iOS 8)

La sua domanda è molto simile a questa:

Multiple views in a UIWindow

Come la risposta ci dice, è possibile registrarsi per le notifiche di modifiche di orientamento e gestire Ridefinisci layout del vostro 'in cima' visualizzazione secondaria quel modo.

+1

Come registrare la vista sul dispositivo per ricevere l'evento di rotazione? Non è il View Controller, quindi non ci sono funzioni delegate per questo. Devo prendere UIDeviceOrientationDidChangeNotification per passare all'orientamento corrispondente? –

2

Ecco una possibile soluzione, sto spiegando in pochi passaggi.

  1. iniziare con una classe di UIViewController ereditata invece di UIView, Diciamo classe denominata TopViewController ereditata da UIViewController
  2. Dal momento che non è possibile registrare la rotazione del dispositivo/interfaccia nella UIView ereditato classe, la classe TopViewController che viene ereditato da UIViewController ha metodi che rispondono a View Rotation Events. Gli eventi di rotazione possono essere catturati ora.
  3. Finalmente è possibile inserire la vista TopViewController nella parte superiore di UIWindow utilizzando lo stesso metodo menzionato nella domanda.

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

Spero che questo aiuti.

+0

Anche la proprietà della vista di UIViewController non viene ruotata. Purtroppo. https://developer.apple.com/library/ios/qa/qa1688/_index.html – khunshan

15

La soluzione migliore che ho trovato è quella di creare una vista contenitore trasparente, aggiungere quel contenitore alla finestra e posizionare l'avviso all'interno del contenitore. È quindi possibile registrarsi per UIApplicationWillChangeStatusBarOrientationNotification per ricevere eventi di rotazione e trasformare il contenitore; questo consente di manipolare in modo indipendente la cornice della segnalazione:

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

È possibile, se si vuole veramente, creare una serie completamente nuova finestra con la sua proprietà windowLevel impostata su UIWindowLevelAlert, che garantirà che la finestra rimanga sopra tutti gli altri viste, compresa la tastiera, ma la gestione delle finestre diventa leggermente più complicata.La soluzione di cui sopra dovrebbe essere sufficiente per la maggior parte delle esigenze.

Il problema con la semplice aggiunta di vista di un controller di vista a una finestra è che non è garantito per ricevere tutte le rotazione e view[Will|Did][Disa|A]ppear: messaggi a meno che non si aggiunge al controller della vista gerarchia tramite addChildViewController: sul controller della vista root.

+0

Ho un problema con questa soluzione. Non riesco a registrare tocchi in quella vista più in alto del contenitore. Gli UIButton non funzionano, per esempio. – asendra

+0

@asendra Sembra che la finestra non sia la finestra chiave, ma potresti voler pubblicare la tua domanda con maggiori dettagli. – Austin

Problemi correlati