Jak wykryć zmianę orientacji w układzie w systemie Android?

110

Właśnie zaimplementowałem funkcję zmiany orientacji - np. Gdy układ zmienia się z pionowego na poziomy (lub odwrotnie). Jak mogę wykryć zakończenie zdarzenia zmiany orientacji.

OrientationEventListenerNie działa. Jak mogę otrzymywać powiadomienia o zdarzeniach dotyczących zmiany orientacji układu?

user403015
źródło
W moim przypadku onCreate () został wywołany, gdy zmienia się orientacja.
Josiel Novaes

Odpowiedzi:

293

Użyj metody onConfigurationChanged Activity. Zobacz poniższy kod:

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

Musisz także edytować odpowiedni plik element w pliku manifestu, aby uwzględnić android: configChanges Wystarczy spojrzeć na poniższy kod:

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

UWAGA: w systemie Android 3.2 (poziom API 13) lub nowszym „rozmiar ekranu” zmienia się również, gdy urządzenie przełącza się między orientacją pionową i poziomą. Dlatego jeśli chcesz zapobiec ponownemu uruchamianiu środowiska uruchomieniowego z powodu zmiany orientacji podczas programowania na poziomie interfejsu API 13 lub wyższym, musisz zadeklarować android: configChanges = "orientacja | screenSize" dla interfejsu API na poziomie 13 lub wyższym .

Mam nadzieję, że to ci pomoże ... :)

Dinesh Sharma
źródło
3
To jest dobre, ale ładuje plik XML układu w folderze layout-land, używa plików układu portretowego xml.
Programmer
23
Aztec Coder, gdy dołączasz „android: configChanges =" orientacja ", deklarujesz, że obsłużysz zmianę orientacji, co oznacza, że ​​Twoja aktywność nie zostanie odtworzona po przełączeniu na krajobraz. Zamiast tego wywoływana jest metoda onConfigurationChanged. Jeśli jest to niepożądane , możesz użyć zmiennej, aby zapamiętać orientację Twojej aktywności i za każdym razem, gdy przechodzisz przez onPause (na przykład), aby sprawdzić, czy orientacja jest nadal taka sama.
Elena
14
Jeśli programujesz dla API na poziomie 13 (3.2) lub wyższym, powinieneś określić android: configChanges = "orientacja | screenSize", w przeciwnym razie onConfigurationChanged nie zostanie nazwany: developer.android.com/guide/topics/resources/ ...
Arne
1
Cześć, tworzę aplikację za pomocą interfejsu API 10 (Android 2.3.3). I doskonale rozpoznaje orientację, gdy używam androida: configChanges = "orientacja | klawiaturaHidden". Ale mój Nexus S z Androidem 4.1.2 nie wykrywa zmiany orientacji, co mam zrobić?
Karthik Andhamil
2
użyj android: configChanges = "orientacja | screenSize" zamiast android: configChanges = "orientacja | klawiaturaHidden" w swoim pliku manifestu i sprawdź ... !!!
Dinesh Sharma
15

Do ładowania układu w układ-lądowych załamującej masz dwa oddzielne układy potem trzeba zrobić setContentVieww onConfigurationChangedmetodzie.

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

Jeśli masz tylko jeden układ, nie ma potrzeby tworzenia setContentView w tej metodzie. po prostu

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
źródło
19
Zamiast nadpisywać, po prostu użyj layout / main.xml i layout-land / main.xml.
Jared Burrows
@JaredBurrows: Zobacz stackoverflow.com/questions/23789605/ ...
B. Clay Shannon
Chciałem wykryć, że moja aktywność została zakończona z powodu obrotu ekranu. Zaimplementowałem onConfigurationChanged(Configuration newConfig)metodę (jak w tej odpowiedzi), ale zamiast obsługiwać ją samodzielnie, ustawiłem flagę logiczną, a następnie wywołałem recreate()metodę, aby Android odtworzył aktywność w normalny sposób.
oszołomiony
Jednym z problemów z tą recreate()metodą jest to, że powoduje ona krótkie miganie ekranu na czarno. Z tego powodu zastosowałem inne podejście: (1) zapisz szerokość ekranu w onCreate(...), (2) porównaj zapisaną szerokość ekranu z aktualną szerokością ekranu w dowolnej metodzie cyklu życia, gdy aktywność jest kończona (np onSaveInstanceState(...).).
oszołomiony
13

Chciałem tylko pokazać, jak zapisać cały pakiet po onConfigurationChanged:

Utwórz nowy pakiet zaraz po zajęciach:

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

Następnie po „protected void onCreate” dodaj to:

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

Jeśli dodasz to, wszystkie twoje klasy ze skrzynek do MainActivity zostaną zapisane.

Najlepszym sposobem jest jednak dodanie tego do pliku AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
źródło
7
To jest mylące. Implementacja onConfigurationChanged()sprawia, że ​​instancja instanceState nie jest niszczona po zmianie orientacji, więc nie musisz jej zapisywać. Możesz chcieć zapisać go dla innych wydarzeń w cyklu życia działania, ale nie wiem.
izzy
5

użyj tej metody

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

I nie zapomnij dodać tego w swoim Androidmainfest.xml

android:configChanges="orientation|screenSize"

lubię to

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

    </activity>
Sai Gopi Me
źródło
2

Zastąp metodę działania onConfigurationChanged

Flavio
źródło
Chciałbym zwrócić uwagę, że bez następującego wiersza w tagu <activity> w manifeście wywołanie zwrotne onConfigurationChanged () nawet nie zostanie wyzwolone. android: configChanges = "orientacja"
Sreekanth Karumanaghat,
1

Chcę tylko zaproponować inną alternatywę, która rzeczywiście będzie dotyczyła niektórych z was, jak wyjaśniono powyżej:

android:configChanges="orientation|keyboardHidden" 

oznacza, że ​​jawnie deklarujemy układ do wstrzyknięcia.

W przypadku, gdy chcemy zachować automatyczne wtryskiwanie dzięki układowi terenu i folderom układu. Wszystko, co musisz zrobić, to dodać go do onCreate:

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

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

Tutaj wyświetlamy lub nie pasek akcji w zależności od orientacji telefonu

Z3nk
źródło
0

Utwórz instancję OrientationEventListenerklasy i włącz ją.

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

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
źródło
2
Proszę, nie niszcz swojej odpowiedzi. Jeśli chcesz ją usunąć, możesz znaleźć przycisk usuwania w lewym dolnym rogu odpowiedzi.
CalvT,
0

Jeśli zaakceptowana odpowiedź nie działa dla Ciebie, upewnij się, że nie zdefiniowałeś w pliku manifestu:

android:screenOrientation="portrait"

Tak jest w moim przypadku.

Jiyeh
źródło
0

W przypadku, gdy jest to przydatne dla niektórych nowszych programistów, ponieważ nie zostało to określone powyżej. Żeby być bardzo wyraźnym:

Jeśli używasz onConfigurationChanged, potrzebujesz dwóch rzeczy :

  1. onConfigurationChangedMetoda w klasie Activity

  2. Określ w swoim manifeście, które zmiany konfiguracji będą obsługiwane przez Twoją onConfigurationChangedmetodę

Fragment manifestu w powyższych odpowiedziach, choć bez wątpienia poprawny dla konkretnej aplikacji, do której należy manifest, NIE jest dokładnie tym, co musisz dodać w swoim manifeście, aby wywołać metodę onConfigurationChanged w swojej klasie działania. tzn. poniższy wpis manifestu może nie być poprawny dla Twojej aplikacji.

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

W powyższym manifeście znajdują się różne akcje systemu Android, android:configChanges=""które mogą wywołać onCreate w cyklu życia działania.

To jest bardzo ważne - te, które NIE zostały określone w manifeście, to te, które wyzwalają twoją onCreate, a te określone w manifeście to te, które wyzwalają twoją onConfigurationChangedmetodę w twojej klasie aktywności.

Musisz więc określić, które zmiany w konfiguracji musisz wykonać samodzielnie. W przypadku Android Encyclopedically Challenged, takiego jak ja, użyłem szybkich podpowiedzi w Android Studio i dodałem prawie każdą możliwą opcję konfiguracji. Wymienienie wszystkich z nich w zasadzie mówiło, że poradzę sobie ze wszystkim, a onCreate nigdy nie zostanie wywołany z powodu konfiguracji.

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

Teraz oczywiście nie chcę zajmować się wszystkim, więc zacząłem eliminować powyższe opcje pojedynczo. Ponowne kompilowanie i testowanie mojej aplikacji po każdym usunięciu.

Kolejna ważna kwestia : jeśli tylko jedna opcja konfiguracji jest obsługiwana automatycznie, która uruchamia twoje onCreate (nie masz jej na liście powyżej w swoim manifeście), wtedy będzie wyglądać tak, jakby onConfigurationChangednie działała. Musisz umieścić wszystkie istotne w swoim manifeście.

Skończyło się na 3, które początkowo wyzwalały onCreate, potem testowałem na S10 + i nadal otrzymywałem onCreate, więc musiałem ponownie wykonać ćwiczenie eliminacyjne i potrzebowałem również |screenSize. Przetestuj więc na wybranych platformach.

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

Więc moja sugestia, chociaż jestem pewien, że ktoś może w tym dziurawić:

  1. Dodaj swoją onConfigurationChangedmetodę do swojej klasy aktywności z TOASTEM lub LOGIEM, aby zobaczyć, kiedy działa.

  2. Dodaj wszystkie możliwe opcje konfiguracji do swojego manifestu.

  3. Sprawdź, czy Twoja onConfigurationChangedmetoda działa, testując aplikację.

  4. Usuń każdą opcję konfiguracji z pliku manifestu pojedynczo, testując aplikację po każdej.

  5. Testuj na jak największej liczbie różnych urządzeń.

  6. Nie kopiuj ani nie wklejaj powyższego fragmentu do swojego pliku manifestu. Aktualizacje Androida zmieniają listę, więc skorzystaj z wyskakujących wskazówek Android Studio, aby upewnić się, że masz je wszystkie.

Mam nadzieję, że to komuś zaoszczędzi trochę czasu.

Moja onConfigurationChangedmetoda tylko dla informacji poniżej. onConfigurationChangedjest wywoływana w cyklu życia po udostępnieniu nowej orientacji, ale przed odtworzeniem interfejsu użytkownika. Dlatego mój pierwszy, ifaby sprawdzić, czy orientacja działa poprawnie, a następnie drugi zagnieżdżony, ifaby spojrzeć na widoczność mojego UI ImageView, również działa poprawnie.

    @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
źródło
0

dla implementacji Kotilin w najprostszej formie - uruchamia się tylko wtedy, gdy ekran zmienia się z pionowego <--> poziomego w razie potrzeby urządzenie wykrywanie odwrócenia (180 stopni) musisz przejść do wartości czujnika grawitacji

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
źródło