Nella mia implementazione ho sottoclassi l'UIView per la mia vista che voglio ruotare e qualcosa come viewController per questa vista che è solo una sottoclasse di NSObject.
In questo viewController eseguo tutti i controlli relativi ai cambi di orientamento, prendo la decisione se dovrei cambiare l'orientamento della mia vista obiettivo, e in caso affermativo, chiamo il metodo della mia vista per cambiarne l'orientamento.
Prima di tutto è necessario correggere l'orientamento dell'intera interfaccia dell'applicazione in modalità Ritratto, in modo che ACCAPtureVideoPreviewLayer rimanga sempre fermo. Questo viene fatto nel MainViewController.h
:
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation`
{
return interfaceOrientation==UIInterfaceOrientationPortrait;
}
E non ha prodotto alcun a tutti gli orientamenti ad eccezione del ritratto.
Per nostra abitudine viewController in grado di monitorare i cambiamenti di orientamento del dispositivo di cui abbiamo bisogno per renderlo un osservatore di notifiche corrispondenti:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
Ho messo queste righe nel metodo della mia viewController (void)awakeFromNib
. Pertanto, ogni volta che viene modificato l'orientamento del dispositivo, viene chiamato il metodo viewController orientationChanged
.
Il suo scopo è verificare quale è il nuovo orientamento del dispositivo, quale era l'ultimo orientamento del dispositivo e decidere se modificarlo. Ecco l'attuazione:
if(UIInterfaceOrientationPortraitUpsideDown==[UIDevice currentDevice].orientation ||
lastOrientation==(UIInterfaceOrientation)[UIDevice currentDevice].orientation)
return;
[[UIApplication sharedApplication]setStatusBarOrientation:[UIDevice currentDevice].orientation animated:NO];
lastOrientation=[UIApplication sharedApplication].statusBarOrientation;
[resultView orientationChanged];
Se l'orientamento è lo stesso di prima o in PortraitUpsideDown poi non fare nulla. Altrimenti imposta l'orientamento della barra di stato su quello corretto, in modo che quando c'è una chiamata in entrata o ossificazione, apparirà sul lato corretto dello schermo. E poi chiamo anche il metodo nella vista di destinazione dove sono eseguite tutte le modifiche corrispondenti per il nuovo orientamento, come la rotazione, il ridimensionamento, lo spostamento degli altri elementi dell'interfaccia in questa vista corrispondente al nuovo orientamento.
Ecco l'attuazione del orientationChanged
in vista di destinazione:
Float32 angle=0.f;
UIInterfaceOrientation orientation=[UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
angle=-90.f*M_PI/180.f;
break;
case UIInterfaceOrientationLandscapeRight:
angle=90.f*M_PI/180.f;
break;
default: angle=0.f;
break;
}
if(angle==0 && CGAffineTransformIsIdentity(self.transform)) return;
CGAffineTransform transform=CGAffineTransformMakeRotation(angle);
[UIView beginAnimations:@"rotateView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.35f];
self.transform=transform;
[UIView commitAnimations];
Naturalmente qui è possibile aggiungere altre modifiche come la traduzione, il ridimensionamento di diversi punti di vista della vostra interfaccia che devono rispondere ai nuovi orientamenti e animare loro.
Inoltre potresti non aver bisogno di viewController per questo, ma fai tutto solo nella classe della tua vista. Spero che l'idea generale sia chiara.
Inoltre, non dimenticare di fermare la notifica di ottenere per l'orientamento cambia quando non è necessario come loro:
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];
avuto problemi simile. Una soluzione _obvious_ non è purtroppo disponibile: speravo di osservare (con KVO) 'transform' del' presentationLayer' del layer della vista senza fortuna - l'osservazione del valore-chiave non è disponibile durante il runtime dell'animazione. Finito usando (probabilmente) la stessa soluzione di te: incorporando il livello di anteprima in un 'UIView' e ruotandolo manualmente. –
Sì, ho anche finito con la rotazione manuale della vista contenente l'anteprimaLayer. Risultò essere non molto complicato. Applico CGAffineTransformMakeRotation() e quindi cambio il frame alla dimensione corretta. Ma ora ho esattamente il comportamento che voglio. – BartoNaz
@BartoNaz Sono in difficoltà da un paio di giorni e tutto ciò che provo non mi dà l'effetto di camera.app in cui AVCaptureVideoPreviewLayer rimane bloccato su una vista e non esegue la rotazione animata. Potresti gentilmente fornire lo snippet di codice funzionante come risposta a questa domanda? Grazie. –