Jak wyłączyć zmianę orientacji na Androidzie?

287

Mam aplikację, której chciałbym używać w trybie portretowym, więc zdefiniowałem Androida: screenOrientation = "portret" w pliku XML manifestu. Działa to OK dla telefonu HTC Magic (i zapobiega zmianie orientacji również w innych telefonach).

Ale mam problem z telefonem HTC G1, gdy otwieram sprzętową klawiaturę QWERTY (nie wirtualną). Moja aktywność pozostaje w trybie portretowym, ale wydaje się, że została zrestartowana i traci wszystkie swoje stany. Nie dzieje się tak w przypadku wersji HTC Hero .

Moja aplikacja jest dość duża, więc nie chcę, aby uruchamiała się ponownie i traciła wszystkie swoje stany po otwarciu klawiatury. Jak mogę temu zapobiec?

Vidar Vestnes
źródło

Odpowiedzi:

317

Aktualizacja kwietnia 2013 r .: Nie rób tego. To nie był dobry pomysł w 2009 roku, kiedy po raz pierwszy odpowiedziałem na pytanie i to naprawdę nie jest dobry pomysł. Zobacz odpowiedź hackbod z powodów:

Unikaj przeładowywania aktywności za pomocą asynchronicznego zadania zmiany orientacji w Androidzie

Dodaj android:configChanges="keyboardHidden|orientation"do pliku AndroidManifest.xml. Mówi to systemowi, jakie zmiany konfiguracji poradzisz sobie sam - w tym przypadku nic nie robiąc.

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

Aby uzyskać więcej informacji, zobacz Dokumentacja konfiguracji dewelopera

Aplikację można jednak przerwać w dowolnym momencie, np. Przez połączenie telefoniczne, dlatego naprawdę należy dodać kod, aby zapisać stan aplikacji po jej wstrzymaniu.

Aktualizacja: Począwszy od Androida 3.2, musisz również dodać „screenSize”:

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

Z podręcznika programisty Obsługa konfiguracji Zmień siebie

Uwaga: Począwszy od Androida 3.2 (poziom API 13) „rozmiar ekranu” zmienia się również, gdy urządzenie przełącza się między orientacją pionową a poziomą. Dlatego jeśli chcesz zapobiec restartowaniu środowiska wykonawczego ze względu na zmianę orientacji podczas programowania dla interfejsu API poziomu 13 lub wyższego (zadeklarowanego przez atrybuty minSdkVersion i targetSdkVersion), oprócz wartości „orientacja” musisz dołączyć wartość „screenSize”. Oznacza to, że musisz zadeklarować android:configChanges="orientation|screenSize". Jeśli jednak aplikacja jest kierowana na interfejs API na poziomie 12 lub niższym, wówczas aktywność zawsze sama obsługuje tę zmianę konfiguracji (ta zmiana konfiguracji nie powoduje ponownego uruchomienia aktywności, nawet jeśli jest uruchomiona na urządzeniu z Androidem 3.2 lub nowszym).

Zawiłości
źródło
36
Aby dodać do tego i być bardzo wyraźnym, Android może bezlitośnie zabić twoją aplikację w dowolnym momencie, niezależnie od zmian orientacji, więc powinieneś użyć onPause () i onSaveInstanceState (), aby zapisać stan, bez względu na wszystko.
Eric Mill
Aktualizacja 3.2 była bardzo przydatna i właśnie mnie blokowała. Nie miałem pojęcia, dlaczego mój program obsługi onConfigurationChanged nie strzelał i to było to. Dzięki!
sweetlilmre,
trzeciego parametru - screenSize nie można znaleźć w 2.3.x, czy powinienem zmienić na screenLayout?
deadfish
2
@Lumma Nie, „screenSize” jest potrzebny tylko dla Androida 3.2 i nowszych. Na jaki poziom interfejsu API kierujesz reklamy? Myślę, że musisz go dodać tylko, jeśli celujesz w poziom 13 lub wyższy. Zaktualizuję odpowiedź, aby wyjaśnić.
Zawiłości
1
Na wypadek, gdyby było to pomocne dla innych osób, znalazłem was oboje <... android: configChanges = "orientacja" ...>, aby zastąpić zmiany i <... android: screenOrientation = "portret" ...> zdefiniuj wartość domyślną.
Sogger,
97

Musisz zmodyfikować plik AndroidManifest.xml, jak wspomniano o Intrications (wcześniej Ashton) i upewnić się, że działanie obsługuje zdarzenie onConfigurationChanged, tak jak chcesz. Tak powinno to wyglądać:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
ubershmekel
źródło
Jak zauważył Dmitrij Zajcew, to lepiej umieścić setRequestedOrientation()in onCreate().
Timmmm,
3
Nie jest onConfigurationChanged()wywoływany wcześniej, onCreate()jeśli więc ustawienie orientacji przed ustawieniem contentViews oncreate jest lepszym podejściem, ustawienie konfiguracji w miejscu, w którym należy, jest również czystsze, więc ta odpowiedź nadal jest dobra.
Samuel
39

Zawsze uważałem, że potrzebujesz obu

android:screenOrientation="nosensor" android:configChanges="keyboardHidden|orientation"
m00sey
źródło
22

Jak powiedziano, zestaw android:configChangesTwojej aktywności (w pliku manifestu) do, keyboardHidden|orientationa następnie:

1) Zastąp onConfigurationChanged()

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

2) Dodaj ten wiersz do swojej aktywności onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

To lepsze niż dodanie tej samej linii onConfigurationChanged, ponieważ aplikacja przełączy się w tryb pionowy, a następnie z powrotem w orientację poziomą (stanie się to tylko raz, ale jest denerwujące).

Możesz także ustawić android:screenOrientation="nosensor"swoją aktywność (w manifeście). Ale w ten sposób nie jesteś w stanie obsłużyć zmian orientacji.

Dmitrij Zajcew
źródło
Co powinienem zrobić, jeśli chcę uniknąć ponownego tworzenia działania po rotacji, ale chcę zezwolić użytkownikowi na zablokowanie orientacji za pomocą ustawień systemu operacyjnego?
programista Androida
@androiddeveloper, że osobne pytanie, które ma już odpowiedź: stackoverflow.com/a/14771495/926907
Dmitry Zaytsev
Twój link dotyczy zmiany treści przeze mnie, gdy zmienia się konfiguracja, ale chcę uniknąć rotacji działania (aby pozostało dokładnie tak, jak wygląda), na wypadek, gdyby użytkownik zdecydował się zablokować orientację za pomocą systemu operacyjnego ustawienia (dostępne na niektórych urządzeniach za pomocą szybkich ustawień, w szufladzie powiadomień).
programista Androida
@androiddeveloper ah, myślę, że zrozumiałem. Następnie spójrz na ten link: developer.android.com/reference/android/… Zgodnie z dokumentami domyślna orientacja powinna już uwzględniać preferencje użytkownika. Jeśli tak nie jest, podejrzewam, że jest to zachowanie specyficzne dla systemu operacyjnego. Z przyjemnością usłyszę o twoich wynikach - teraz też mnie to interesuje :)
Dmitry Zaytsev
Wiem, że domyślna obsłuży preferencje użytkownika, ale także odtwarza aktywność po obróceniu ekranu, czego nie chcę mieć.
programista Androida
20

Użyj tego..

    android:screenOrientation="portrait"
Muhammad Aamir Ali
źródło
13

W metodzie OnCreate swojej aktywności użyj tego kodu:

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

Teraz twoja orientacja zostanie ustawiona na pionową i nigdy się nie zmieni.

Numenor
źródło
4
Dzięki temu nie zapobiegniesz ponownemu uruchamianiu działania przy każdej zmianie konfiguracji orientacji.
AxeEffect,
Nie działa to również, jeśli wprowadzisz działanie z poprzedniego działania w orientacji poziomej.
w3bshark,
10

W pliku AndroidManifest.xml do każdego działania, które chcesz zablokować, dodaj ostatni screenOrientationwiersz:

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

Lub Android: screenOrientation = "krajobraz" .

Gil Allen
źródło
8

W pliku androidmanifest.xml :

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

lub

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Jorgesys
źródło
6

Aby zablokować ekran kodem, musisz użyć faktycznego obrotu ekranu (0, 90, 180, 270) i ​​musisz znać jego naturalną pozycję, w smartfonie naturalną pozycją będzie portret i tablet, będzie krajobraz.

Oto kod (metody blokowania i odblokowywania), został przetestowany na niektórych urządzeniach (smartfonach i tabletach) i działa świetnie.

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);
}
PoOk
źródło
jaki parametr należy przekazać jako aktywność?
WISHY
Działanie, które wywołuje metodę blokowania / odblokowywania orientacji. Jest to publiczna statyczna metoda użyteczności, którą można wywołać z różnych działań.
PoOk
1
Działa świetnie, ale poważnie, na Androidzie, dlaczego musimy robić to wszystko *** tylko dla orientacji ekranu blokady? !!!
Cocorico,
tak. Ten blokuje orientację, tak jak my w manifeście. Zapobiegnie to wywoływaniu funkcji onConfigurationChanged. Czy istnieje metoda, która blokuje interfejs użytkownika w trybie poziomym i nadal wywołuje właściwość onConfigurationChanged. Podobnie jak aplikacja aparatu w Androidzie
Ajith Memana
W zestawie SDK 18+ znajduje się flaga SCREEN_ORIENTATION_LOCKED, która wydaje się działać, ale nadal chcesz użyć powyższego kodu do obsługi każdego urządzenia
DominicM
2

W Visual Studio Xamarin:

  1. Dodaj:

using Android.Content.PM; do ciebie lista przestrzeni nazw aktywności.

  1. Dodaj:

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

jako atrybut twojej klasy, tak:

[Activity(ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : Activity
{...}
Roy Doron
źródło
To pytanie dotyczy Androida, a nie Xamarin.Android
Trevor Hart
1

Dodaj

android:configChanges="keyboardHidden|orientation|screenSize" 

do twojego manifestu.

saurabh
źródło
wewnątrz tagu <activity>
Ege Kuzubasioglu,
0

Pamiętaj, że żadna z metod nie działa teraz!

W Android Studio 1 jednym prostym sposobem jest dodanie android:screenOrientation="nosensor".

To skutecznie blokuje orientację ekranu.

kefalian
źródło