Come disabilitare la modifica dell'orientamento su Android?


287

Ho un'applicazione che vorrei solo usare in modalità verticale, quindi ho definito android: screenOrientation = "portrait" nel file manifest XML. Funziona bene con il telefono HTC Magic (e impedisce anche cambiamenti di orientamento su altri telefoni).

Ma ho un problema con il telefono HTC G1 quando apro la tastiera hardware QWERTY (non la tastiera virtuale). La mia attività rimane in modalità verticale, ma sembra riavviarsi e perde tutti i suoi stati. Questo non succede con la versione di HTC Hero .

La mia applicazione è piuttosto grande, quindi non voglio che si riavvii e perda tutti i suoi stati quando viene aperta la tastiera. Come posso impedirlo?



Risposte:


317

Aggiornamento aprile 2013: non farlo. Non è stata una buona idea nel 2009 quando ho risposto per la prima volta alla domanda e in realtà non è una buona idea ora. Vedi questa risposta da hackbod per motivi:

Evita di ricaricare l'attività con asynctask sul cambio di orientamento in Android

Aggiungi android:configChanges="keyboardHidden|orientation"al tuo AndroidManifest.xml. Questo dice al sistema quali modifiche alla configurazione dovrai gestire, in questo caso senza fare nulla.

<activity android:name="MainActivity"
     android:screenOrientation="portrait"
     android:configChanges="keyboardHidden|orientation">

Vedi Config di riferimento per gli sviluppatoriCambia per maggiori dettagli.

Tuttavia, l'applicazione può essere interrotta in qualsiasi momento, ad esempio tramite una telefonata, quindi è necessario aggiungere un codice per salvare lo stato dell'applicazione quando viene messa in pausa.

Aggiornamento: a partire da Android 3.2, devi anche aggiungere "screenSize":

<activity
    android:name="MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="keyboardHidden|orientation|screenSize">

Dalla guida per sviluppatori Gestione della configurazione Modifica te stesso

Attenzione: a partire da Android 3.2 (livello API 13), la "dimensione dello schermo" cambia anche quando il dispositivo passa dall'orientamento verticale a quello orizzontale. Pertanto, se si desidera impedire il riavvio del runtime a causa della modifica dell'orientamento durante lo sviluppo per livello API 13 o superiore (come dichiarato dagli attributi minSdkVersion e targetSdkVersion), è necessario includere il valore "screenSize" oltre al valore "orientamento". Cioè, devi dichiarare android:configChanges="orientation|screenSize". Tuttavia, se l'applicazione ha come target API livello 12 o inferiore, la tua attività gestisce sempre questa modifica della configurazione stessa (questa modifica della configurazione non riavvia l'attività, anche quando è in esecuzione su un dispositivo Android 3.2 o versione successiva).


36
Solo per aggiungere a questo ed essere davvero esplicito, Android può uccidere senza pietà la tua applicazione in qualsiasi momento, indipendentemente dai cambiamenti di orientamento, quindi dovresti usare onPause () e onSaveInstanceState () per salvare lo stato, non importa quale.
Eric Mill,

L'aggiornamento 3.2 è stato molto utile ed è stato ciò che mi stava bloccando. Non avevo idea del perché il mio gestore onConfigurationChanged non funzionasse e basta. Grazie!
Sweetlilmre,

il terzo parametro - screenSize non può essere trovato in 2.3.x, devo cambiare in screenLayout?
pesce morto il

2
@Lumma No, "screenSize" è necessario solo per Android 3.2 e versioni successive. A quale livello API stai prendendo di mira? Penso che sia necessario aggiungerlo solo se hai come target il livello 13 o superiore. Aggiornerò la risposta per chiarire.
Intricazioni il

1
Nel caso sia utile ad altre persone, ho trovato entrambi <... android: configChanges = "orientamento" ...> per sovrascrivere le modifiche e <... android: screenOrientation = "portrait" ...> per definire il valore predefinito.
Soggetto

97

È necessario modificare AndroidManifest.xml come menzionato Intrications (precedentemente Ashton) e assicurarsi che l'attività gestisca l'evento onConfigurationChanged come lo si desidera. Ecco come dovrebbe apparire:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

Come notato da Dmitry Zaitsev, è meglio mettere setRequestedOrientation()dentro onCreate().
Timmmm,

3
Non onConfigurationChanged()viene chiamato prima onCreate()se l'impostazione dell'orientamento prima di impostare contentViews in oncreate è un approccio migliore , l'impostazione della configurazione a cui appartiene è anche più pulita, quindi questa risposta è ancora valida.
Samuel,

39

Ho sempre trovato che hai bisogno di entrambi

android:screenOrientation="nosensor" android:configChanges="keyboardHidden|orientation"

22

Come detto, impostare la android:configChangespropria attività (nel file manifest) su keyboardHidden|orientatione quindi:

1) Ignora onConfigurationChanged()

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //here you can handle orientation change
}

2) Aggiungi questa riga a quella della tua attività onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

È meglio che aggiungere la stessa linea a onConfigurationChanged, perché la tua app passerà in modalità verticale e poi tornerà in orizzontale (accadrà solo una volta, ma è fastidioso).

Inoltre puoi impostare la android:screenOrientation="nosensor"tua attività (in manifest). Ma in questo modo non sei in grado di gestire i cambiamenti di orientamento.


Cosa devo fare se desidero evitare di ricreare l'attività al momento della rotazione, ma desidero consentire all'utente di bloccare l'orientamento tramite le impostazioni del sistema operativo?
sviluppatore Android

@androiddeveloper una domanda separata, che ha già una risposta: stackoverflow.com/a/14771495/926907
Dmitry Zaytsev

Il tuo link riguarda la modifica del contenuto da solo quando cambia la configurazione, tuttavia desidero evitare la rotazione dell'attività (in modo che rimanga esattamente come appare) nel caso in cui l'utente abbia scelto di bloccare l'orientamento tramite il sistema operativo impostazioni (disponibili su alcuni dispositivi tramite le impostazioni rapide, nel riquadro delle notifiche).
sviluppatore Android

@androiddeveloper ah, penso di aver capito. Dai un'occhiata a questo link: developer.android.com/reference/android/… Secondo i documenti, l'orientamento predefinito dovrebbe già tenere conto delle preferenze dell'utente. In caso contrario, sospetto che si tratti di un comportamento specifico del sistema operativo. Sarei felice di conoscere i tuoi risultati - ora sono anche interessato a questo :)
Dmitry Zaytsev

So che l'impostazione predefinita gestirà le preferenze dell'utente, ma ricrea anche l'attività quando si ruota lo schermo, che è qualcosa che non voglio avere.
sviluppatore Android


13

Nel metodo OnCreate della tua attività usa questo codice:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

Ora il tuo orientamento sarà impostato su verticale e non cambierà mai.


4
Con ciò non si impedisce il riavvio dell'attività ogni volta che cambia la configurazione dell'orientamento.
AxeEffect

Inoltre, questo non funziona se si inserisce l'attività da un'attività precedente in orientamento orizzontale.
w3bshark,

10

Nel file AndroidManifest.xml, per ogni attività che desideri bloccare aggiungi l'ultima screenOrientationriga:

android:label="@string/app_name"
android:name=".Login"
android:screenOrientation="portrait" >

O android: screenOrientation = "landscape" .


8

Nel tuo file androidmanifest.xml :

   <activity android:name="MainActivity" android:configChanges="keyboardHidden|orientation">

o

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

6

Per bloccare lo schermo in base al codice devi utilizzare la rotazione effettiva dello schermo (0, 90, 180, 270) e devi conoscerne la posizione naturale, in uno smartphone la posizione naturale sarà verticale e in un tablet, sarà paesaggio.

Ecco il codice (metodi di blocco e sblocco), è stato testato su alcuni dispositivi (smartphone e tablet) e funziona benissimo.

public static void lockScreenOrientation(Activity activity)
{   
    WindowManager windowManager =  (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);   
    Configuration configuration = activity.getResources().getConfiguration();   
    int rotation = windowManager.getDefaultDisplay().getRotation(); 

    // Search for the natural position of the device    
    if(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&  
       (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) ||  
       configuration.orientation == Configuration.ORIENTATION_PORTRAIT &&   
       (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270))   
    {   
        // Natural position is Landscape    
        switch (rotation)   
        {   
            case Surface.ROTATION_0:    
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);    
                break;      
            case Surface.ROTATION_90:   
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
            break;      
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
                break;
        }
    }
    else
    {
        // Natural position is Portrait
        switch (rotation) 
        {
            case Surface.ROTATION_0: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
            break;   
            case Surface.ROTATION_90: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
            break;   
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;
        }
    }
}

public static void unlockScreenOrientation(Activity activity)
{
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

quale parametro deve essere passato come attività?
WISHY,

L'attività che chiama il metodo per bloccare / sbloccare il suo orientamento. Questo è un metodo di utilità statica pubblica che può essere chiamato da attività diverse.
PoOk,

1
Funziona alla grande, ma, sul serio, Android, perché dobbiamo fare tutto questo solo per l'orientamento della schermata di blocco? !!!
Cocorico,

sì. Questo blocca l'orientamento come facciamo nel manifest. Ciò eviterà più la chiamata a onConfigurationChanged. Esiste un metodo che blocca l'interfaccia utente su Landscape e invoca ancora onConfigurationChanged. Proprio come fa l'app della fotocamera in Android
Ajith Memana,

C'è un flag SCREEN_ORIENTATION_LOCKED su SDK 18+ che sembra funzionare ma vorresti comunque usare il codice sopra per supportare tutti i dispositivi
DominicM

2

In Visual Studio Xamarin:

  1. Inserisci:

using Android.Content.PM; al tuo elenco di spazi dei nomi delle attività.

  1. Inserisci:

[Activity(ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]

come attributo alla tua classe, in questo modo:

[Activity(ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : Activity
{...}

Questa domanda è su Android, non su Xamarin.Android
Trevor Hart il


0

Si noti che nessuno dei metodi sembra funzionare ora!

In Android Studio 1 è possibile aggiungere un modo semplice android:screenOrientation="nosensor".

Ciò blocca efficacemente l'orientamento dello schermo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.