Nie ładuj ponownie aplikacji, gdy zmienia się orientacja

152

Po prostu nie potrzebuję nic do zmiany, gdy ekran jest obracany. Moja aplikacja wyświetla losowy obraz po pierwszym załadowaniu, a obrócenie urządzenia nie powinno wybierać innego losowego obrazu. Jak mogę (po prostu) powstrzymać to zachowanie?

Jimmy D.
źródło
1
Możliwe jest również zablokowanie (i ewentualnie odblokowanie) orientacji ekranu za pomocą kodu. Po prostu zadzwoń Screen.lockOrientation(this)z github.com/delight-im/Android-BaseLib/blob/master/Source/src/im/… w tym celu. Umożliwia odblokowanie, czego manifest nie umożliwia.
krakanie
@Escobar Ceaser Jakie jest właściwe rozwiązanie tego pytania, chociaż mam takie same wymagania.
Prabs
Chciałbym to zrobić programowo w kodzie.
pollaris

Odpowiedzi:

249

Generalnie można to zrobić na trzy sposoby:

  1. Jak sugerowały niektóre odpowiedzi, możesz rozróżnić przypadki, w których Twoja aktywność została utworzona po raz pierwszy i z której została przywrócona savedInstanceState. Odbywa się to poprzez nadpisanie onSaveInstanceStatei sprawdzenie parametru onCreate.

  2. Możesz zablokować aktywność w jednej orientacji, dodając android:screenOrientation="portrait"(lub "landscape") do <activity>w swoim manifeście.

  3. Możesz powiedzieć systemowi, że zamierzasz samodzielnie obsługiwać zmiany ekranu, określając android:configChanges="orientation|screenSize"w <activity>tagu. W ten sposób aktywność nie zostanie odtworzona, ale zamiast tego otrzyma oddzwonienie (które możesz zignorować, ponieważ nie jest to dla Ciebie przydatne).

Osobiście wybrałbym (3). Oczywiście, jeśli zablokowanie aplikacji w jednej z orientacji Ci odpowiada, możesz również wybrać (2).

Xion
źródło
13
Więc w przypadku # 3 mówisz, że wszystko, co muszę zrobić, to dodać tę linię do mojego manifestu? Ponieważ to nie działa.
Jimmy D
16
@EscobarCeaser, dla Androida 3.2 i nowszych potrzebujeszandroid:configChanges="orientation|screenSize"
Pacerier,
9
android:configChanges="orientation|screenSize"pracuje dla mnie. Dzięki @Pacerier
Don Larynx
1
proszę, zaktualizuj swój przypadek odpowiedzi nr 3 o android:configChanges="orientation|screenSize"wartość API> = 13, ponieważ wiele osób uważa Twoją odpowiedź za główną!
radistao
215

Odpowiedź Xiona była bliska, ale nr 3 ( android:configChanes="orientation") nie zadziała, chyba że aplikacja ma poziom API 12 lub niższy.

Na poziomie API 13 lub wyższym rozmiar ekranu zmienia się, gdy zmienia się orientacja, więc nadal powoduje to zniszczenie działania i rozpoczęcie po zmianie orientacji.

Po prostu dodaj atrybut „screenSize”, tak jak poniżej:

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

Teraz, gdy zmienisz orientację (i zmieni się rozmiar ekranu), działanie zachowuje swój stan i onConfigurationChanged()jest wywoływane. Spowoduje to zachowanie wszystkiego, co jest na ekranie (np. Strony internetowej w widoku sieci Web) po zmianie orientacji.

Nauczyłem się tego z tej witryny: http://developer.android.com/guide/topics/manifest/activity-element.html

Jest to również najwyraźniej zła praktyka, więc przeczytaj poniższy link dotyczący obsługi zmian w czasie wykonywania:

http://developer.android.com/guide/topics/resources/runtime-changes.html

Corbin
źródło
2
Dzięki ... jego praca po dodaniu "screenSize" z "orientacją"
Pratik Butani
Działa w Samsung Galaxy Nexus Android 4.2.1! android:configChanges="orientation|screenSize"
Vincent Ducastel
Niesamowity. Pracowałem nad kodem przez wiele godzin, aby rozwiązać problem, który miałem z ponownym ładowaniem aktywności i filmem zaczynającym się od początku. I oto rozwiązanie! ++++ 1
Mathias Asberg
6
Zła praktyka? Pfft, ludzie w prawdziwym życiu mają terminy i jeśli to działa, to działa;)
Kacy
Jeśli to zła praktyka, to dlaczego zebrała tyle pozytywnych głosów?
Sharp Edge
26

Musisz tylko przejść do AndroidManifest.xmli wewnątrz lub w etykietach działań, musisz wpisać ten wiersz kodu, jak ktoś tam powiedział:

android:configChanges="orientation|screenSize"

Więc będziesz miał coś takiego:

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

Mam nadzieję, że to działa!

Josue Rocha
źródło
nie ładuje mojego układu lay-landu. :( nie zadziałało dla mnie
piyush poriya
16
<activity android:name="com.example.abc" 
 android:configChanges="orientation|screenSize"></activity>

Po prostu dodaj android:configChanges="orientation|screenSize"w zakładce aktywności pliku manifestu.

Tak więc aktywność nie zostanie ponownie uruchomiona po zmianie orientacji.

Aiyaz Parmar
źródło
To działa. Ale kiedy używam osobnego układu dla każdej orientacji layout.xml i layout-land.xml. stosuje układ poziomy dla obu orientacji. Jeśli używam tylko "orientacji", to daje to, czego oczekuję, ale przeładowuje. Czy mógłbyś w tym pomóc?
Karthikeyan Ve
1
@KarthikeyanVe To jest problem, gdy próbujesz oszukiwać. Będziesz musiał ponownie uruchomić swoją aktywność, aby zmienić układ. Śmiało i po prostu użyj prawdziwego rozwiązania, które wykorzystuje onSaveInstanceState()i onCreate().
Marc Plano-Lesay
@ MarcPlano-Lesay i jak mam to zrobić?
Ahsan
@Weaboo rzeczywiste rozwiązanie jest powiązane w pytaniu: developer.android.com/guide/topics/resources/ ...
Marc Plano-Lesay
@ MarcPlano-Lesay Mam oddzielny układ dla trybu pionowego i poziomego, jeśli otworzę aplikację w trybie poziomym lub pionowym, działa dobrze, ale za każdym razem, gdy próbuję zmienić orientację w czasie wykonywania, zamyka moją aplikację, jednak kiedy loguję się do mojej aplikacji a następnie przejdź do MainActivity i spróbuj zmienić orientację, wczytuje to działanie ponownie i działa dobrze. Teraz pytanie brzmi: dlaczego? Czy w moim kodzie jest błąd logiczny? Idk, ale kilka razy próbowałem debugować aplikację i nie mogę nic znaleźć. Ponadto nie chcę ponownie uruchamiać mojej aktywności, dlaczego nie możemy po prostu dostosować odpowiedniego układu po zmianie konfiguracji?
Ahsan
10

Z mojego doświadczenia wynika, że ​​właściwie lepiej jest po prostu radzić sobie ze zmianami orientacji we właściwy sposób, zamiast próbować podbijać inne zachowanie.

Należy zapisać obraz, który jest aktualnie wyświetlany w programie onSaveInstanceState()i przywrócić go poprawnie po onCreate()ponownym uruchomieniu aplikacji .

dmon
źródło
# 3 to doskonale poprawne rozwiązanie. Jest to dokładne narzędzie stworzone do rozwiązania tego konkretnego problemu. Dlaczego mówisz, że to butowanie?
Pacerier
1
@Pacerier Po prostu przeczytaj dokumentację. „Uwaga: android:configChangesnależy unikać używania i używać go tylko w ostateczności. Przeczytaj artykuł Obsługa zmian w czasie wykonywania, aby uzyskać więcej informacji o tym, jak prawidłowo obsłużyć ponowne uruchomienie z powodu zmiany konfiguracji”.
Marc Plano-Lesay
Czy mógłbyś opublikować przykład zapisywania i przywracania.
pollaris
6

To rozwiązanie jest zdecydowanie najlepiej działające. W swoim pliku manifestu dodaj

<activity
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:name="your activity name"
    android:label="@string/app_name" 
    android:screenOrientation="landscape">
  </activity

W swojej klasie aktywności dodaj następujący kod

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

    }
}
Raj
źródło
4

dodaj android:configChanges="keyboardHidden|orientation|screenSize"dla wszystkich tagów działań aplikacji w manifeście.

Oubaida AlQuraan
źródło
3

Po prostu dodaj to do swojego AndroidManifest.xml

<activity android:screenOrientation="landscape">

Chodzi mi o to, że jest tag aktywności, dodaj to jako kolejny parametr. Jeśli potrzebujesz orientacji pionowej, zmień orientację poziomą na pionową. Mam nadzieję że to pomoże.

Egor
źródło
Nie chcę odebrać możliwości obracania ekranu. po prostu nie chcę, aby moja aplikacja była ponownie ładowana ... jak wspomniałem.
Jimmy D
ps ... to i tak nie działa. wymusza po prostu wyświetlanie aplikacji w określonej orientacji. obrót ekranu nadal powoduje ponowne wczytanie aktywności
Jimmy D
3

W pliku manifestu dodaj to do każdego działania. To pomoże

android:configChanges = "orientation|keyboard|keyboardHidden|screenLayout|screenSize"
Jevgenij Kononov
źródło
screenLayout działał dla mnie, uniemożliwiłem odświeżanie podczas zmiany rozmiaru aplikacji dla podzielonego ekranu na Androidzie
Terren
2

Wszystkie powyższe odpowiedzi nie działają dla mnie. Więc naprawiłem, wspominając o labelz screenOrientationjak poniżej. Teraz wszystko w porządku

<activity android:name=".activity.VideoWebViewActivity"
        android:label="@string/app_name"
        android:configChanges="orientation|screenSize"/>
Bahu
źródło
1

Zapisz szczegóły obrazu w swoim onPause()lub onStop()i użyj go w, onCreate(Bundle savedInstanceState)aby przywrócić obraz.

EDYTOWAĆ:

Więcej informacji na temat rzeczywistego procesu można znaleźć tutaj http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle, ponieważ w Honeycomb różni się on od poprzednich wersji Androida.

techiServices
źródło
właściwie powinieneś to zrobić w metodzie onSaveInstanceState ()
Willi Mentzel
1

po prostu użyj : android:configChanges="keyboardHidden|orientation"

Masoud Banimahd
źródło
1

Jak wspomniał Pacerier,

android:configChanges="orientation|screenSize"

Don Larynx
źródło
-1

Nie wiem, czy najlepsze rozwiązanie, ale opisuję to tutaj:

Przede wszystkim potrzebujesz certyfikatu z twoją klasą. Aplikacja twojej aplikacji jest w twoim manifeście:

<application
    android:name=".App"
    ...

Po drugie, w mojej aplikacji klasowej podobało mi się:

public class App extends Application {
    public static boolean isOrientationChanged = false;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onConfigurationChanged(@NotNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
                newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            isOrientationChanged = true;
        }
    }

}

Po trzecie, musisz ustawić flagę na zmianę orientacji, w moim przypadku zawsze ustawiam ją, gdy wywoływana jest poprzednia aktywność w nawigacji aplikacji, więc dzwonię tylko raz, gdy tworzona jest późniejsza aktywność.

isOrientationChanged = false;

Więc za każdym razem, gdy zmieniam orientację mojego ekranu w tym kontekście, ustawiam go za każdym razem, gdy zmienia to ustawienie, sprawdza, czy nastąpiła zmiana orientacji, jeśli tak, sprawdza ją na podstawie wartości tej flagi.

Zasadniczo musiałem go używać za każdym razem, gdy wykonywałem asynchroniczne żądanie retrofitu, które nazywał każdą chwilą, która zmieniała orientację, ciągle zawieszając aplikację:

if (!isOrientationChanged) {
    presenter.retrieveAddress(this, idClient, TYPE_ADDRESS);
}

Nie wiem, czy to najbardziej eleganckie i najpiękniejsze rozwiązanie, ale przynajmniej tutaj funkcjonalne :)

michel566
źródło
-2

Dodaj ten kod po onCreatemetodzie, w swoim działaniu zawierającymWebView

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);    
}

@Override
protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);    
}
Amir Aslam
źródło
1
Jak by to działało? Czy nie mówisz czegoś wyraźnie do środowiska wykonawczego, co w przeciwnym razie zostałoby zrobione domyślnie?
Danielson,