Ottenere l'orientamento del dispositivo prima di ruotarlo o forzarlo all'avvio. Qualche idea?
-
08-07-2019 - |
Domanda
Ho una scadenza presto e ho un bug molto fastidioso davanti a me e nessuna idea su come risolverlo. Il problema è che a volte il dispositivo non sa quale sia il suo orientamento prima che sia stato ruotato e quindi incasina i frame nelle istruzioni condizionali:
if (orient == UIInterfaceOrientationPortrait || orient == 0){
r = CGRectMake(0.0, 0.0, 320.0, 480.0);
// draw stuff
} else {
r = CGRectMake(0.0, 0.0, 480.0, 320.0);
// draw stuff
}
Questo bug può essere facilmente riprodotto se tengo il dispositivo sul tavolo o nelle mani (posizione orizzontale) ed eseguo la mia applicazione, disegna rettangoli di tipo orizzontale nella schermata del tipo verticale.
Le mie domande sono: posso in qualche modo ottenere il giusto orientamento in questo tipo di situazione? Peccato che non possa essere riprodotto nel simulatore, quindi non sono sicuro che il codice che ho incollato sia responsabile di questo errore, ma quello è il posto in cui aggiusto i frame della vista in base all'orientamento. Forse c'è un altro (corretto) modo per farlo? E forse posso forzare l'applicazione in modalità verticale fino a quando non verrà attivato l'evento di rotazione?
Soluzione
Non penso che sia un bug. Quando l'iPhone è seduto sul tavolo, tutta la gravità viene misurata lungo l'asse Z. Per determinare l'orientamento del dispositivo viene utilizzato l'asse x-y, ma nessuna accelerazione viene misurata accanto ad essi nel tuo scenario.
EDIT: ulteriori spiegazioni:
Questa immagine mostra come sono orientati gli assi su iPhone: alt text http://developer.apple. com / iphone / biblioteca / documentazione / UIKit / Reference / UIAcceleration_Class / Arte / device_axes.jpg
Quindi, quando hai l'iPhone sul retro, viene applicata un'accelerazione di -1g sull'asse z. Per ricevere le accelerazioni misurate è sufficiente registrare un delegato che implementa UIAccelerometerDelegate
con l'istanza condivisa UIAccelerometer
. Vedi AccelerometerGraph prova come è fatto.
Per determinare se l'iPhone si trova sul tavolo fai qualcosa del genere:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
// lowPass filter first
// now choose orientation
if (fabs([acceleration z]) >= 0.9) // sitting on the table: choose new mode or lock current mode
if (fabs([acceleration y]) >= 0.9) // probably portrait mode
if (fabs([acceleration x]) >= 0.9) // probably landscape mode
}
La precisione dell'accelerometro è 18mG = 0.018G
quindi tienilo a mente.
Inoltre, è necessario isolarsi dagli effetti dei cambi di movimento istantanei, un semplice filtro LowPass si adatta perfettamente a questa fattura. L'esempio AccelerometerGraph mostra come implementare tale filtro.
Scegli anche un intervallo di aggiornamento molto basso se non hai bisogno di molta precisione, 30Hz dovrebbe andare bene per i tuoi scopi.
Altri suggerimenti
Il sensore che determina l'orientamento del dispositivo non è né infallibile né intelligente. Se poni il telefono sul tavolo e poi lo cammini, come dovrebbe sapere che è sottosopra?