rotar rotacion quiero que plus pantalla gire girar gira desactivar iphone objective-c cocoa-touch

quiero - rotacion de pantalla iphone 7



¿Hay alguna forma documentada de configurar la orientación del iPhone? (17)

Tengo una aplicación en la que me gustaría admitir la rotación del dispositivo en ciertas vistas, pero otras no tienen ningún sentido en el modo Paisaje, así que al cambiar las vistas me gustaría forzar a que la rotación se establezca en vertical.

Existe un setter de propiedad no documentado en UIDevice que hace el truco, pero obviamente genera una advertencia de compilación y podría desaparecer con una futura revisión del SDK.

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];

¿Hay alguna forma documentada de forzar la orientación?

Actualización: pensé que daría un ejemplo ya que no estoy buscando shouldAutorotateToInterfaceOrientation ya que ya lo he implementado.

Quiero que mi aplicación admita paisaje y retrato en la Vista 1, pero solo retrato en la Vista 2. Ya he implementado shouldAutorotateToInterfaceOrientation para todas las vistas, pero si el usuario está en modo horizontal en la Vista 1 y luego cambia a la Vista 2, quiero forzar el teléfono para girar de nuevo a Portrait.


Tengo una aplicación en la que me gustaría admitir la rotación del dispositivo en ciertas vistas, pero otras no tienen ningún sentido en el modo Paisaje, así que al cambiar las vistas me gustaría forzar a que la rotación se establezca en vertical.

Me doy cuenta de que la publicación original anterior en este hilo es muy antigua ahora, pero tuve un problema similar a ella, es decir. todas las pantallas de mi aplicación son solo de retrato, con la excepción de una pantalla, que el usuario puede rotar entre el paisaje y el retrato.

Esto fue bastante sencillo, pero al igual que otras publicaciones, quería que la aplicación vuelva automáticamente al retrato, independientemente de la orientación actual del dispositivo, cuando regrese a la pantalla anterior.

La solución que implementé fue ocultar la barra de navegación mientras estaba en modo horizontal, lo que significa que el usuario solo puede regresar a las pantallas anteriores mientras está en el modo vertical. Por lo tanto, todas las otras pantallas solo pueden estar en retrato.

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)pInterfaceOrientation { BOOL lHideNavBar = self.interfaceOrientation == UIInterfaceOrientationPortrait ? NO : YES; [self.navigationController setNavigationBarHidden:lHideNavBar animated:YES]; }

Esto también tiene el beneficio adicional para mi aplicación ya que hay más espacio de pantalla disponible en modo horizontal. Esto es útil porque la pantalla en cuestión se usa para mostrar archivos PDF.

Espero que esto ayude.


Encontré una solución y escribí algo en francés (pero el código está en inglés). here

La forma es agregar el controlador a la vista de ventana (el controlador debe poseer una buena implementación de la función shouldRotate ....).


Estaba teniendo un problema donde tenía un UIViewController en la pantalla, en un UINavigationController , en orientación horizontal. Sin embargo, cuando el siguiente controlador de vista se empuja en el flujo, necesitaba que el dispositivo volviera a la orientación vertical.

Lo que noté, fue que el método shouldAutorotateToInterfaceOrientation: no se llama cuando un nuevo controlador de vista se inserta en la pila, sino que se invoca cuando un controlador de vista se saca de la pila .

Aprovechando esto, estoy usando este fragmento de código en una de mis aplicaciones:

- (void)selectHostingAtIndex:(int)hostingIndex { self.transitioning = YES; UIViewController *garbageController = [[[UIViewController alloc] init] autorelease]; [self.navigationController pushViewController:garbageController animated:NO]; [self.navigationController popViewControllerAnimated:NO]; BBHostingController *hostingController = [[BBHostingController alloc] init]; hostingController.hosting = [self.hostings objectAtIndex:hostingIndex]; [self.navigationController pushViewController:hostingController animated:YES]; [hostingController release]; self.transitioning = NO; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (self.transitioning) return (toInterfaceOrientation == UIInterfaceOrientationPortrait); else return YES; }

Básicamente, al crear un controlador de vista vacío, empujarlo hacia la pila e inmediatamente apagarlo, es posible hacer que la interfaz vuelva a la posición de retrato. Una vez que el controlador ha aparecido, simplemente presiono el controlador que tenía la intención de presionar en primer lugar. Visualmente, se ve muy bien: el controlador de vista vacío y arbitrario nunca lo ve el usuario.


Esto es lo que uso (Obtiene algunas advertencias de compilación pero funciona tanto en el simulador como en el iPhone)

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];


Esto es mucho después del hecho, pero solo en caso de que llegue alguien que no esté usando un controlador de navegación y / o no desee utilizar métodos no documentados:

UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release];

Es suficiente presentar y descartar un controlador de vista de vanilla.

Obviamente, aún deberá confirmar o denegar la orientación en la anulación de shouldAutorotateToInterfaceOrientation. Pero esto causará que AuthorAte ... sea llamado nuevamente por el sistema.


Esto funciona para mí (gracias Henry Cooke):

El objetivo para mí era tratar solo con cambios en las orientaciones del paisaje.

método init:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];

- (void)orientationChanged:(NSNotification *)notification { //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = 0; NSLog(@"Right"); break; case UIDeviceOrientationLandscapeLeft: r = M_PI; NSLog(@"Left"); break; default:return; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; }


Esto ya no es un problema en el SDK de iPhone 3.1.2 posterior. Ahora parece respetar la orientación solicitada de la vista que se vuelve a colocar en la pila. Eso probablemente significa que necesitaría detectar versiones anteriores de iPhone OS y solo aplicar el setOrientation cuando es anterior a la última versión.

No está claro si el análisis estático de Apple comprenderá que está trabajando en torno a las antiguas limitaciones del SDK. Personalmente, Apple me ha pedido que elimine la llamada al método en mi próxima actualización, por lo que aún no estoy seguro de si el hackeo de dispositivos más antiguos pasará por el proceso de aprobación.


FWIW, aquí está mi implementación de la configuración de orientación manual (para ir en el controlador de vista raíz de tu aplicación, natch):

-(void)rotateInterfaceToOrientation:(UIDeviceOrientation)orientation{ CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = -(M_PI / 2); break; case UIDeviceOrientationLandscapeLeft: r = M_PI / 2; break; } if( r != 0 ){ CGSize sz = bounds.size; bounds.size.width = sz.height; bounds.size.height = sz.width; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; }

junto con el siguiente método UINavigationControllerDelegate (suponiendo que esté utilizando un UINavigationController ):

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ // rotate interface, if we need to UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; BOOL bViewControllerDoesSupportCurrentOrientation = [ viewController shouldAutorotateToInterfaceOrientation: orientation ]; if( !bViewControllerDoesSupportCurrentOrientation ){ [ self rotateInterfaceToOrientation: UIDeviceOrientationPortrait ]; } }

Eso se encarga de rotar la vista raíz según si un UIViewController entrante admite la orientación actual del dispositivo. Finalmente, querrá conectar rotateInterfaceToOrientation a los cambios reales de orientación del dispositivo para imitar la funcionalidad estándar de iOS. Agregue este controlador de eventos al mismo controlador de vista raíz:

-(void)onUIDeviceOrientationDidChangeNotification:(NSNotification*)notification{ UIViewController *tvc = self.rootNavigationController.topViewController; UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; // only switch if we need to (seem to get multiple notifications on device) if( orientation != [[ UIApplication sharedApplication ] statusBarOrientation ] ){ if( [ tvc shouldAutorotateToInterfaceOrientation: orientation ] ){ [ self rotateInterfaceToOrientation: orientation ]; } } }

Finalmente, regístrese para UIDeviceOrientationDidChangeNotification notificaciones de UIDeviceOrientationDidChangeNotification en init o loadview manera:

[[ NSNotificationCenter defaultCenter ] addObserver: self selector: @selector(onUIDeviceOrientationDidChangeNotification:) name: UIDeviceOrientationDidChangeNotification object: nil ]; [[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ];


Hay una manera simple de forzar programáticamente al iPhone a la orientación necesaria, utilizando dos de las respuestas ya proporcionadas por kdbdallas , Josh :

//will rotate status bar [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; //will re-rotate view according to statusbar UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release];

Funciona de maravilla :)

EDITAR:

para iOS 6 necesito agregar esta función: (funciona en viewcontroller modal)

- (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight); }


He estado cavando y cavando en busca de una buena solución para esto. Encontré esta publicación de blog que hace el truco: eliminar su vista más externa de la UIWindow clave y UIWindow agregarla, el sistema volverá a consultar los métodos shouldAutorotateToInterfaceOrientation: de sus viewcontrollers, haciendo que se aplique la orientación correcta. Véalo : iphone forzando a la vista a reorientar


La respuesta de Josh funciona bien para mí.

Sin embargo, prefiero publicar una notificación de "la orientación cambió, actualice la UI" . Cuando un controlador de vista recibe esta notificación, llama a shouldAutorotateToInterfaceOrientation: lo que le permite establecer cualquier orientación al devolver YES para la orientación que desea.

[[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];

El único problema es que esto obliga a una reorientación sin una animación. Tendría que ajustar esta línea entre beginAnimations: y commitAnimations para lograr una transición sin problemas.

Espero que ayude.


Lo resolví bastante fácilmente al final. Probé todas las sugerencias anteriores y todavía me quedé corto, así que esta fue mi solución:

En el ViewController que debe permanecer en el modo horizontal (izquierda o derecha), escucho los cambios de orientación:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];

Luego en didRotate:

- (void) didRotate:(NSNotification *)notification { if (orientationa == UIDeviceOrientationPortrait) { if (hasRotated == NO) { NSLog(@"Rotating to portait"); hasRotated = YES; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); [UIView commitAnimations]; } } else if (UIDeviceOrientationIsLandscape( orientationa)) { if (hasRotated) { NSLog(@"Rotating to lands"); hasRotated = NO; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0)); self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); [UIView commitAnimations]; } }

Tenga en cuenta todas las Súper Vistas / Subvistas que utilizan el ajuste automático, ya que view.bounds / frame se restablecen de forma explícita ...

La única salvedad de este método para mantener la vista Paisaje, es la animación inherente que cambia entre las orientaciones que tiene que ocurrir, cuando sería mejor hacer que parezca que no tiene cambios.


No creo que esto sea posible en el tiempo de ejecución, aunque podrías aplicar una transformación de 90 grados a tu UI.


Por lo que puedo decir, el método setOrientation: no funciona (o tal vez ya no funciona). Esto es lo que estoy haciendo para hacer esto:

primero, ponga esta definición en la parte superior de su archivo, justo debajo de #imports:

#define degreesToRadian(x) (M_PI * (x) / 180.0)

luego, en el método viewWillAppear:

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); }

si quieres que esté animado, puedes envolverlo todo en un bloque de animación, así:

[UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:1.25]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); } [UIView commitAnimations];

Luego, en el controlador de modo retrato, puede hacer lo contrario: verifique si está actualmente en el modo paisaje y, de ser así, gírelo de nuevo a Retrato.


Si está utilizando UIViewControllers, existe este método:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

Devuelve NO para los controladores de vista que contienen las vistas que no quieres rotar.

Más información aquí


Si quiere obligarlo a girar de vertical a horizontal, aquí está el código. Solo tenga en cuenta que necesita ajustar el centro de su vista. Noté que el mío no colocó la vista en el lugar correcto. De lo contrario, funcionó perfectamente. Gracias por el consejo.

if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){ [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.center = CGPointMake(160.0f, 240.0f); [UIView commitAnimations]; }


Solución iOS 6:

[[[self window] rootViewController] presentViewController:[[UIViewController alloc] init] animated:NO completion:^{ [[[self window] rootViewController] dismissViewControllerAnimated:NO completion:nil]; }];

El código exacto depende de cada aplicación y también de dónde la coloque (la utilicé en mi AppDelegate). Reemplace [[self window] rootViewController] con lo que usa. Estaba usando un UITabBarController .