Wie erkenne ich Orientierungsänderungen im Layout in Android?

109

Ich habe gerade eine Orientierungsänderungsfunktion implementiert - z. B. wenn sich das Layout von Hochformat zu Querformat ändert (oder umgekehrt). Wie kann ich erkennen, wann das Orientierungsänderungsereignis beendet ist?

Das OrientationEventListenerhat nicht funktioniert. Wie kann ich Benachrichtigungen über Ereignisse zur Änderung der Layoutausrichtung erhalten?

user403015
quelle
In meinem Fall wurde onCreate () aufgerufen, wenn sich die Ausrichtung ändert.
Josiel Novaes

Antworten:

291

Verwenden Sie die Aktivitätsmethode onConfigurationChanged . Siehe folgenden Code:

@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();
    }
}

Sie müssen auch die entsprechenden bearbeiten Element in Ihrer Manifest-Datei, um das Android einzuschließen: configChanges Siehe den folgenden Code:

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

HINWEIS: Bei Android 3.2 (API-Stufe 13) oder höher ändert sich auch die "Bildschirmgröße", wenn das Gerät zwischen Hoch- und Querformat wechselt. Wenn Sie also einen Neustart der Laufzeit aufgrund von Orientierungsänderungen bei der Entwicklung für API-Level 13 oder höher verhindern möchten, müssen Sie android: configChanges = "Ausrichtung | screenSize" für API-Level 13 oder höher deklarieren .

Hoffe das wird dir helfen ... :)

Dinesh Sharma
quelle
3
Dies ist gut, aber es lädt die Layout-XML nicht in den Ordner layout-land, in dem die Layout-XML-Layoutdateien verwendet werden.
Programmierer
22
Aztec Coder: Wenn Sie "android: configChanges =" Orientierung "einschließen, erklären Sie, dass Sie die Orientierungsänderung behandeln. Dies bedeutet, dass Ihre Aktivität beim Wechsel in die Landschaft nicht neu erstellt wird. Stattdessen wird onConfigurationChanged aufgerufen. Wenn dies unerwünscht ist Sie können eine Variable verwenden, um sich an die Ausrichtung Ihrer Aktivität zu erinnern, und jedes Mal, wenn Sie auf Pause gehen (zum Beispiel), um zu überprüfen, ob die Ausrichtung immer noch dieselbe ist.
Elena
14
Wenn Sie für API Level 13 (3.2) oder höher entwickeln, sollten Sie android angeben: configChanges = "Orientierung | Bildschirmgröße", andernfalls wird onConfigurationChanged nicht aufgerufen: developer.android.com/guide/topics/resources/…
Arne
1
Hallo, ich baue meine App mit API 10 (Android 2.3.3). Und es erkennt die Ausrichtung perfekt, wenn ich Android benutze: configChanges = "Ausrichtung | TastaturHidden". Aber mein Nexus S, auf dem Android 4.1.2 ausgeführt wird, erkennt die Orientierungsänderung nicht. Was soll ich tun?
Karthik Andhamil
2
Verwenden Sie android: configChanges = "Ausrichtung | Bildschirmgröße" anstelle von android: configChanges = "Ausrichtung | Tastatur versteckt" in Ihrer Manifestdatei und überprüfen Sie ... !!!
Dinesh Sharma
15

Um das Layout in den Ordner layout-land zu laden , müssen Sie zwei separate Layouts haben, die Sie setContentViewin der onConfigurationChangedMethode erstellen müssen .

@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);
    }
}

Wenn Sie nur ein Layout haben, ist es nicht erforderlich, setContentView in dieser Methode zu erstellen. einfach

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
quelle
19
Anstatt zu überschreiben, verwenden Sie einfach die Datei layout / main.xml und layout-land / main.xml.
Jared Burrows
@ JaredBurrows: Siehe stackoverflow.com/questions/23789605/…
B. Clay Shannon
Ich wollte feststellen, dass meine Aktivität aufgrund einer Bildschirmdrehung abgebrochen wurde. Ich habe die onConfigurationChanged(Configuration newConfig)Methode implementiert (wie in dieser Antwort), aber anstatt sie selbst zu behandeln, habe ich ein Boolesches Flag gesetzt und die recreate()Methode dann aufgerufen , damit Android die Aktivität auf normale Weise neu erstellt.
benommen
Ein Problem bei dieser recreate()Methode besteht darin, dass der Bildschirm kurz schwarz blinkt. Aus diesem Grund habe ich einen anderen Ansatz gewählt: (1) Speichern der Bildschirmbreite in onCreate(...), (2) Vergleichen der gespeicherten Bildschirmbreite mit der aktuellen Bildschirmbreite in einer beliebigen Lebenszyklusmethode, wenn die Aktivität beendet wird (z onSaveInstanceState(...). B. ).
benommen
13

Ich wollte Ihnen nur einen Weg zeigen, wie Sie Ihr gesamtes Bundle nach onConfigurationChanged speichern können:

Erstelle direkt nach deiner Klasse ein neues Bundle:

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

Als nächstes fügen Sie nach "protected void onCreate" Folgendes hinzu:

@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");
}

Wenn Sie dies hinzufügen, werden alle Ihre Klassen in MainActivity gespeichert.

Am besten fügen Sie dies jedoch in Ihr AndroidManifest ein:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
quelle
7
Das ist irreführend. Durch die Implementierung onConfigurationChanged()wird Ihr instanceState nicht zerstört, wenn sich die Ausrichtung ändert, sodass Sie ihn nicht speichern müssen. Möglicherweise möchten Sie es für andere Ereignisse im Aktivitätslebenszyklus speichern, aber ich weiß es nicht.
Izzy
5

Verwenden Sie diese Methode

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

Und vergessen Sie nicht, dies in Ihre Androidmainfest.xml aufzunehmen

android:configChanges="orientation|screenSize"

so was

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

    </activity>
Sai Gopi ich
quelle
2

Überschreiben Sie die Aktivitätsmethode onConfigurationChanged

Flavio
quelle
Ich möchte darauf hinweisen, dass ohne die folgende Zeile innerhalb des <activity> -Tags im Manifest der Rückruf von onConfigurationChanged () nicht einmal ausgelöst würde. android: configChanges = "Orientierung"
Sreekanth Karumanaghat
1

Ich möchte nur eine andere Alternative vorschlagen, die einige von Ihnen betrifft, wie oben erläutert:

android:configChanges="orientation|keyboardHidden" 

impliziert, dass wir das zu injizierende Layout explizit deklarieren.

Für den Fall, dass wir die automatische Injektion dank der Layout-Land- und Layout-Ordner beibehalten möchten. Alles was Sie tun müssen, ist es zu onCreate hinzuzufügen:

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

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

Hier wird die Aktionsleiste je nach Ausrichtung des Telefons angezeigt oder nicht

Z3nk
quelle
0

Erstellen Sie eine OrientationEventListenerKlasseninstanz und aktivieren Sie sie.

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

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
quelle
2
Bitte zerstören Sie Ihre Antwort nicht. Wenn Sie es löschen möchten, finden Sie die Schaltfläche Löschen unten links in Ihrer Antwort.
CalvT
0

Wenn die akzeptierte Antwort für Sie nicht funktioniert, stellen Sie sicher, dass Sie sie nicht in der Manifestdatei definiert haben:

android:screenOrientation="portrait"

Welches ist mein Fall.

Jiyeh
quelle
0

Für den Fall, dass dies für einige neuere Entwickler von Nutzen ist, da es oben nicht angegeben ist. Nur um ganz explizit zu sein:

Sie benötigen zwei Dinge, wenn Sie onConfigurationChanged verwenden :

  1. Eine onConfigurationChangedMethode in Ihrer Aktivitätsklasse

  2. Geben Sie in Ihrem Manifest an, welche Konfigurationsänderungen von Ihrer onConfigurationChangedMethode behandelt werden

Das Manifest-Snippet in den obigen Antworten ist zwar zweifellos für die jeweilige App, zu der das Manifest gehört, korrekt, aber NICHT genau das, was Sie in Ihr Manifest einfügen müssen, um die onConfigurationChanged-Methode in Ihrer Aktivitätsklasse auszulösen. Das heißt, der folgende Manifesteintrag ist möglicherweise nicht korrekt für Ihre App.

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

Im obigen Manifesteintrag gibt es verschiedene Android-Aktionen, für android:configChanges=""die onCreate in Ihrem Aktivitätslebenszyklus ausgelöst werden kann.

Dies ist sehr wichtig - Diejenigen, die NICHT im Manifest angegeben sind, lösen Ihr onCreate aus, und diejenigen, die im Manifest angegeben sind, lösen Ihre onConfigurationChangedMethode in Ihrer Aktivitätsklasse aus.

Sie müssen also ermitteln, welche Konfigurationsänderungen Sie selbst vornehmen müssen. Für Android Encyclopedically Challenged wie mich habe ich das Popup mit schnellen Hinweisen in Android Studio verwendet und fast jede mögliche Konfigurationsoption hinzugefügt. Das Auflisten all dieser Elemente hat im Grunde gesagt, dass ich alles erledigen würde und onCreate aufgrund von Konfigurationen niemals aufgerufen wird.

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

Jetzt möchte ich natürlich nicht alles erledigen, also habe ich begonnen, die oben genannten Optionen einzeln zu eliminieren. Nach jedem Entfernen meine App neu erstellen und testen.

Ein weiterer wichtiger Punkt : Wenn nur eine Konfigurationsoption automatisch behandelt wird, die Ihr onCreate auslöst (Sie haben es oben in Ihrem Manifest nicht aufgeführt), scheint onConfigurationChangedes nicht zu funktionieren. Sie müssen alle relevanten in Ihr Manifest aufnehmen.

Am Ende hatte ich 3, die ursprünglich onCreate auslösten, dann habe ich auf einem S10 + getestet und ich bekam immer noch onCreate, also musste ich meine Eliminierungsübung erneut machen und ich brauchte auch das |screenSize. Testen Sie also auf einer Auswahl von Plattformen.

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

Also mein Vorschlag, obwohl ich sicher bin, dass jemand Löcher in diese stechen kann:

  1. Fügen Sie Ihre onConfigurationChangedMethode in Ihrer Aktivitätsklasse mit einem TOAST oder LOG hinzu, damit Sie sehen können, wann sie funktioniert.

  2. Fügen Sie Ihrem Manifest alle möglichen Konfigurationsoptionen hinzu.

  3. Bestätigen Sie, dass Ihre onConfigurationChangedMethode funktioniert, indem Sie Ihre App testen.

  4. Entfernen Sie jede Konfigurationsoption einzeln aus Ihrer Manifestdatei und testen Sie anschließend Ihre App.

  5. Testen Sie auf möglichst vielen Geräten.

  6. Kopieren Sie meinen obigen Ausschnitt nicht in Ihre Manifestdatei. Android-Updates ändern die Liste. Verwenden Sie daher die Pop-out-Hinweise für Android Studio, um sicherzustellen, dass Sie alle erhalten.

Ich hoffe das spart jemandem etwas Zeit.

Meine onConfigurationChangedMethode nur zur Info unten. onConfigurationChangedwird im Lebenszyklus aufgerufen, nachdem die neue Ausrichtung verfügbar ist, aber bevor die Benutzeroberfläche neu erstellt wurde. Daher iffunktioniert meine erste Überprüfung der Ausrichtung korrekt, und die zweite, die verschachtelt ist if, um die Sichtbarkeit meiner UI ImageView zu überprüfen, funktioniert ebenfalls korrekt.

    @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);
            }

        }
    }
DMur
quelle
0

Für die Kotilin-Implementierung in der einfachsten Form - wird nur ausgelöst, wenn sich der Bildschirm von Hoch- zu Querformat ändert, wenn das Gerät eine Flip-Erkennung (180 Grad) benötigt, müssen Sie die Werte des Schwerkraftsensors eingeben

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")


    }
}
alpha911
quelle