Come rilevare il cambiamento di orientamento nel layout in Android?


110

Ho appena implementato una funzione di modifica dell'orientamento, ad esempio quando il layout cambia da verticale a orizzontale (o viceversa). Come posso rilevare quando l'evento di cambio di orientamento è terminato.

Il OrientationEventListenernon ha funzionato. Come posso ricevere notifiche sugli eventi di modifica dell'orientamento del layout?


Nel mio caso, onCreate () è stato chiamato quando cambia l'orientamento.
Josiel Novaes

Risposte:


293

Utilizzare il metodo di attività onConfigurationChanged . Vedere il codice seguente:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Devi anche modificare il file elemento nel file manifest per includere android: configChanges Basta vedere il codice di seguito:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

NOTA: con Android 3.2 (livello API 13) o superiore, 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 del cambio di orientamento durante lo sviluppo per il livello API 13 o superiore, è necessario dichiarare android: configChanges = "orientamento | screenSize" per il livello API 13 o superiore .

Spero che questo ti aiuti ... :)


3
Questo va bene, ma non carica il layout xml nella cartella layout-land e usa i file di layout xml portrait.
Programmatore

22
Aztec Coder, quando includi "android: configChanges =" orientamento "dichiari che gestirai la modifica dell'orientamento, il che significa che la tua attività non verrà ricreata quando passi alla visualizzazione orizzontale. Invece, viene chiamato onConfigurationChanged. Se questo non è desiderato , potresti usare una variabile per ricordare l'orientamento della tua attività e ogni volta che vai in Pausa (ad esempio) per verificare se l'orientamento è sempre lo stesso.
Elena

14
Se stai sviluppando per il livello API 13 (3.2) o superiore, devi specificare android: configChanges = "Orientamento | screenSize", altrimenti onConfigurationChanged non verrà chiamato: developer.android.com/guide/topics/resources/…
Arne

1
Ciao, sto creando la mia app con API 10 (Android 2.3.3). E riconosce perfettamente l'orientamento quando uso android: configChanges = "orientamento | keyboardHidden". Ma il mio Nexus S con Android 4.1.2 non rileva il cambio di orientamento, cosa devo fare?
Karthik Andhamil

2
usa android: configChanges = "orientamento | screenSize" invece di android: configChanges = "orientamento | keyboardHidden" nel tuo file manifest e controlla ... !!!
Dinesh Sharma

15

Per caricare il layout nella cartella layout-land significa che hai due layout separati, quindi devi creare setContentViewnel onConfigurationChangedmetodo.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Se si dispone di un solo layout, non è necessario creare setContentView in questo metodo. semplicemente

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

19
Invece di sovrascrivere, usa semplicemente layout / main.xml e layout-land / main.xml.
Jared Burrows


Volevo rilevare che la mia attività è stata interrotta a causa di una rotazione dello schermo. Ho implementato il onConfigurationChanged(Configuration newConfig)metodo (come in questa risposta), ma invece di gestirlo da solo, ho impostato un flag booleano e quindi ho chiamato il recreate()metodo in modo che Android ricreasse l'attività nel suo modo normale.
stordito

Un problema con il recreate()metodo è che fa lampeggiare brevemente lo schermo in nero. Per questo motivo ho utilizzato un altro approccio: (1) salva la larghezza dello schermo in onCreate(...), (2) confronta la larghezza dello schermo salvata con la larghezza dello schermo corrente in qualsiasi metodo del ciclo di vita quando l'attività viene terminata (ad esempio onSaveInstanceState(...)).
stordito

13

Volevo solo mostrarti un modo per salvare tutto il tuo bundle dopo onConfigurationChanged:

Crea un nuovo pacchetto subito dopo la tua lezione:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Successivamente, dopo "protected void onCreate" aggiungi questo:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Se lo aggiungi, tutte le tue classi create in MainActivity verranno salvate.

Ma il modo migliore è aggiungerlo nel tuo AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

7
Questo è fuorviante. L'implementazione onConfigurationChanged()fa in modo che il tuo instanceState non venga distrutto quando cambia l'orientamento, quindi non devi salvarlo. Potresti salvarlo per altri eventi nel ciclo di vita dell'attività, ma non lo so.
izzy

5

usa questo metodo

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

E non dimenticare di aggiungere questo nel tuo Androidmainfest.xml

android:configChanges="orientation|screenSize"

come questo

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>

2

Sostituisci il metodo dell'attività onConfigurationChanged


Vorrei sottolineare che senza la riga seguente all'interno del tag <activity> nel manifest, la richiamata onConfigurationChanged () non verrebbe nemmeno attivata. android: configChanges = "orientamento"
Sreekanth Karumanaghat,

1

Voglio solo proporre un'altra alternativa che riguarderà alcuni di voi, appunto, come spiegato sopra:

android:configChanges="orientation|keyboardHidden" 

implica che dichiariamo esplicitamente il layout da inserire.

Nel caso volessimo mantenere l'iniezione automatica grazie al layout-land e alle cartelle di layout. Tutto quello che devi fare è aggiungerlo a onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Qui, mostriamo o meno la barra delle azioni a seconda dell'orientamento del telefono


0

Crea un'istanza di OrientationEventListenerclasse e abilitala.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();

2
Per favore, non vandalizzare la tua risposta. Se vuoi eliminarlo, puoi trovare il pulsante Elimina in basso a sinistra della tua risposta.
CalvT

0

Se la risposta accettata non funziona per te, assicurati di non aver definito nel file manifest:

android:screenOrientation="portrait"

Qual è il mio caso.


0

Nel caso in cui questo sia utile per alcuni sviluppatori più recenti perché non è specificato sopra. Giusto per essere molto espliciti:

Hai bisogno di due cose se usi onConfigurationChanged :

  1. Un onConfigurationChangedmetodo nella tua classe di attività

  2. Specifica nel tuo manifest quali modifiche alla configurazione verranno gestite dal tuo onConfigurationChangedmetodo

Lo snippet di manifest nelle risposte precedenti, sebbene senza dubbio corretto per la particolare app a cui appartiene il manifest, NON è esattamente ciò che devi aggiungere nel tuo manifest per attivare il metodo onConfigurationChanged nella tua Activity Class. ad esempio, la voce di manifest di seguito potrebbe non essere corretta per la tua app.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

Nella voce manifest sopra, ci sono varie azioni Android per android:configChanges="" quali è possibile attivare onCreate nel ciclo di vita delle attività.

Questo è molto importante: quelli NON specificati nel manifest sono quelli che attivano il tuo onCreate e quelli specificati nel manifest sono quelli che attivano il tuo onConfigurationChangedmetodo nella tua Activity Class.

Quindi è necessario identificare quali modifiche alla configurazione è necessario gestire da soli. Per Android Encyclopedically Challenged come me, ho utilizzato il pop-out dei suggerimenti rapidi in Android Studio e aggiunto in quasi tutte le possibili opzioni di configurazione. L'elenco di tutti questi fondamentalmente diceva che avrei gestito tutto e onCreate non verrà mai chiamato a causa delle configurazioni.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Ora ovviamente non voglio gestire tutto, quindi ho iniziato a eliminare le opzioni di cui sopra una alla volta. Ricostruzione e test della mia app dopo ogni rimozione.

Un altro punto importante : se c'è solo un'opzione di configurazione gestita automaticamente che attiva il tuo onCreate (non l'hai elencato nel tuo manifest sopra), allora apparirà comeonConfigurationChanged . Devi inserire tutti quelli rilevanti nel tuo manifest.

Ho finito con 3 che si stavano attivando originariamente su onCreate, poi ho provato su un S10 + e stavo ancora ricevendo onCreate, quindi ho dovuto ripetere il mio esercizio di eliminazione e avevo anche bisogno di |screenSize. Quindi prova su una selezione di piattaforme.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Quindi il mio suggerimento, anche se sono sicuro che qualcuno possa fare dei buchi in questo:

  1. Aggiungi il tuo onConfigurationChangedmetodo nella tua classe di attività con un TOAST o LOG in modo da poter vedere quando funziona.

  2. Aggiungi tutte le opzioni di configurazione possibili al tuo manifest.

  3. Conferma che il tuo onConfigurationChangedmetodo funziona testando la tua app.

  4. Rimuovi ogni opzione di configurazione dal tuo file manifest una alla volta, testando la tua app dopo ciascuna.

  5. Prova su una varietà di dispositivi più ampia possibile.

  6. Non copiare / incollare il mio snippet sopra nel tuo file manifest. Gli aggiornamenti Android cambiano l'elenco, quindi utilizza i suggerimenti di Android Studio pop-out per assicurarti di averli tutti.

Spero che questo faccia risparmiare tempo a qualcuno.

Il mio onConfigurationChangedmetodo solo per le informazioni di seguito. onConfigurationChangedviene chiamato nel ciclo di vita dopo che il nuovo orientamento è disponibile, ma prima che l'interfaccia utente sia stata ricreata. Quindi il mio primo ifcontrollo che l'orientamento funzioni correttamente, quindi il secondo annidato ifper esaminare la visibilità della mia interfaccia utente ImageView funziona correttamente.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }

0

per l'implementazione di Kotilin nella forma più semplice - si attiva solo quando lo schermo cambia da verticale <--> orizzontale se necessario un dispositivo di rilevamento del capovolgimento (180 gradi) dovrai inserire i valori del sensore di gravità

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}
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.