bar - iOS: deshabilitar la autorotación para una subvista
large title navigation bar swift (3)
Tengo una jerarquía de vistas anidadas para una aplicación de iPad que admite cambios de orientación. Se ve similar a lo siguiente.
UIViewController
UIView
- UIView
- UIImageView (disable rotation)
- UIImageView
- UIView (disable rotation)
- UIView
- UIView
...
Me gustaría bloquear la orientación de algunas de mis subvistas y permitir que otras giren automáticamente y cambien el tamaño. Parece que no puedo encontrar la manera de lograr esto.
Un enfoque parece ser rotar las subvistas manualmente dentro de willAnimateRotationToInterfaceOrientation:
Eso no es particularmente atractivo dado que el SDK está ejecutando una rotación que simplemente estaría deshaciendo.
¿Hay una manera de simplemente deshabilitar los cambios de orientación para subvistas o algún otro método para reestructurar mi jerarquía?
Aquí hay otra manera. Simplemente coloque este código en su viewController viewDidLoad:
YourAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
// the view you don''t want rotated (there could be a heierarchy of views here):
UIView *nonRotatingView = [[UIView alloc] initWithFrame:CGRectMake(100,0,30,500)];
nonRotatingView.backgroundColor = [UIColor purpleColor];
// make sure self.view and its children are transparent so you can see through to this view that will not be rotated behind self.view.
[delegate.window insertSubview:nonRotatingView belowSubview:self.view];
// you can''t put it in the front using:
// [delegate.window insertSubview:nonRotatingView aboveSubview:self.view];
// It will show up the same as before
// you should declare nonRotatingView as a property so you can easily access it for removal, etc.
La autorrotación se maneja mediante el control UIViewController ( shouldAutorotateToInterfaceOrientation:
, por lo que un enfoque es organizar su jerarquía de manera que las vistas giratorias sean administradas por un controlador de vista y las vistas no giratorias por otro controlador de vista. Estas dos vistas de raíz de UIViewController necesitan agregarse a la ventana / superview.
La sutileza aquí es que si tiene dos vistas del controlador de vista en el mismo nivel (es decir, agregado a través de addSubview:
, solo el primer controlador de vista (generalmente el control de control de ventana de la ventana) recibirá el mensaje shouldAutorotateToInterfaceOrientation:
Utilicé este enfoque para lograr una barra de herramientas que gira, mientras que la vista principal no.
La sección de preguntas y respuestas técnicas de Apple QA1688 ("¿Por qué mi UIViewController no gira con el dispositivo?") Habla un poco sobre este problema.
Actualización para iOS 6:
La autorrotación ahora usa los UIViewController
shouldAutorotate
y shouldAutorotate
. shouldAutorotate
devuelve YES
de forma predeterminada, pero recuerde que un controlador de vista distinto del rootViewController
cuya vista es una subvista directa de la ventana NO recibirá las devoluciones de llamada de rotación de todos modos.
Código de muestra para iOS 6:
Cree un nuevo proyecto utilizando la plantilla "Aplicación de vista única" y asegúrese de que la casilla "Usar guiones gráficos" esté marcada. Usaremos la clase ViewController
provista como el controlador de vista giratoria (¡renómbrelo si lo desea!) Y crearemos una segunda subclase NonRotatingViewController
llamada NonRotatingViewController
. Aunque este controlador de vista nunca recibirá las devoluciones de llamada de rotación, para completar y aclarar agregue el siguiente código en NonRotatingViewController.m
:
- (BOOL)shouldAutorotate
{
return NO;
}
En el archivo MainStoryboard
, arrastre un nuevo objeto de controlador de vista y establezca su clase en NonRotatingViewController
, y establezca su ID de Storyboard en "NonRotatingVC". Mientras esté allí, cambie el color de fondo de la vista del controlador de la vista giratoria a claro (la vista no giratoria se agregará debajo de esta) y agregue una etiqueta a cada vista. En AppDelegate.m
, agregue el siguiente código:
#import "NonRotatingViewController.h"
// ...
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
[self.window addSubview:nonRotatingVC.view];
return YES;
}
Esto es solo crear una instancia de un controlador de vista no giratorio y agregar su vista directamente a la ventana (NB, en este punto, el guión gráfico ya ha configurado el control de visualización de la ventana).
Ejecutar el proyecto. ¡Gire el dispositivo y maravíllese con la vista de una etiqueta que gira mientras la otra permanece inmóvil!
Código de muestra pre iOS 6:
Hice esto en un nuevo proyecto: una nueva aplicación basada en vista funcionará bien. Agregue dos nuevos controladores de vista: RotatingViewController
y NonRotatingViewController
. Dentro de cada una de sus puntas, acabo de agregar una etiqueta para describir si la vista debe rotar o no. Agregue el siguiente código:
'' RotatingViewController.m
''
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
'' NonRotatingViewController.m
''
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) { // Or whatever orientation it will be presented in.
return YES;
}
return NO;
}
'' AppDelegate.m
''
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
self.rotatingViewController = rotating;
[rotating release];
NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
self.nonRotatingViewController = nonRotating;
[nonRotating release];
[self.window addSubview:self.rotatingViewController.view];
[self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];
[self.window makeKeyAndVisible];
return YES;
}
Espero que esto ayude.
Mi enfoque para resolver este problema es hacer una contramedida usando UINotification
para detectar la rotación automática y girar la vista al revés.
Encuentra el código completo aquí:
https://gist.github.com/ffraenz/5945301
- (void)orientationDidChangeNotificationReceived:(NSNotification *)notification
{
// find out needed compass rotation
// (as a countermeasure to auto rotation)
float rotation = 0.0;
if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
rotation = M_PI;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
rotation = M_PI / 2.0;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
rotation = M_PI / (- 2.0);
// rotate compass without auto rotation animation
// iOS rotation animation duration is 0.3
// this excludes the compassView from the auto rotation
// (same effect as in the camera app where controls do rotate and camera viewport don''t)
[UIView animateWithDuration:0.3 animations:^(void) {
self.compassView.transform = CGAffineTransformMakeRotation(rotation);
}];
}