In certe occasioni è indispensabile forzare l’interface orientation di una view. Pensiamo ad una applicazione che voglia visualizzare un contenuto e che questo contenuto sia fruibile solo in landscape. Normalmente l’utente parte da una posizione portrait (verticale) del device. Si vuole che all’entrata di una certa view l’orientation si sposti in landscape in modo automatico anche se il device è ancora in posizione verticale. Bene non esiste una metodo ufficiale per questa attività. Esistono però due soluzioni alternative valide, ognuna con i suoi pro e i suoi contro e sono:
- Utilizzare una proprietà non documentata della classe UIDevice
- Gestire manualmente la rotazione di tutti gli elementi grafici
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
- Genera un warning in compilazione in quanto non è una funzione esposta dall’SDK
- Non è garantito che funzioni con le versioni future dell’SDK proprio perché non è ufficialmente supportata
- (void)viewWillAppear:(BOOL)animated { UIScreen *screen = [UIScreen mainScreen]; CGFloat screenWidth = screen.bounds.size.width; CGFloat screenHeight = screen.bounds.size.height; UIAccelerationValue x = self.navigationController.navigationBar.frame.origin.x; UIAccelerationValue y = self.navigationController.navigationBar.frame.origin.y; [UIView beginAnimations:@"orientation" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.navigationController.view.transform = CGAffineTransformIdentity; self.navigationController.view.transform = CGAffineTransformMakeRotation(M_PI_2); self.navigationController.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); self.navigationController.view.center = CGPointMake(screenWidth/2.0, screenHeight/2.0); self.navigationController.navigationBar.frame = CGRectMake(x, y, 480, 32); [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES]; [UIView commitAnimations]; } - (void)viewWillDisappear:(BOOL)animated { UIScreen *screen = [UIScreen mainScreen]; CGFloat screenWidth = screen.bounds.size.width; CGFloat screenHeight = screen.bounds.size.height; UIAccelerationValue x = self.navigationController.navigationBar.frame.origin.x; UIAccelerationValue y = self.navigationController.navigationBar.frame.origin.y; [UIView beginAnimations:@"orientation" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.navigationController.view.transform = CGAffineTransformIdentity; self.navigationController.view.transform = CGAffineTransformMakeRotation(M_PI * 2); self.navigationController.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); self.navigationController.view.center = CGPointMake(screenWidth/2.0, screenHeight/2.0); [self.navigationController.navigationBar setFrame:CGRectMake(x, y, 320, 44)]; [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES]; [UIView commitAnimations]; }
- C’è un leggero difetto grafico in fase di rotazione se la NavigationBar contiene elementi al suo interno come button o immagini. In pratica c’è un leggero sfarfallio degli elementi che si adattano alla nuova dimensione della NavigationBar. Non mi è ancora chiaro questo problema.
- E’ sicuramente più lento di una soluzione nativa