Jak zablokować orientację podczas działania

107

Czy istnieje sposób na zablokowanie orientacji podczas działania? Na przykład chciałbym zezwolić użytkownikowi na zablokowanie ekranu w orientacji poziomej, jeśli użytkownik jest obecnie w orientacji poziomej, i przełączanie opcji menu.

Jared
źródło

Odpowiedzi:

133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Wezwany do działania, zablokuje go w poziomie. Poszukaj innych flag w klasie ActivityInfo. Możesz zablokować go z powrotem do portretu lub sterować czujnikiem / suwakiem.

Więcej informacji tutaj: http://www.devx.com/wireless/Article/40792

haseman
źródło
13
Ok dzięki. To działa świetnie. Pozwoli to uzyskać obecną orientację. getResources (). getConfiguration (). orientacja
Jared
7
Ostrożny! Musisz rozróżnić między tym, co zwraca getConfiguration (), a tym, czego chce setRequestedOrientation - zobacz moją odpowiedź poniżej, aby uzyskać szczegółowe informacje
Andy Weinstein
istnieje problem z tym podejściem. Upewnij się, że przejrzałeś komentarz do tej odpowiedzi
Bugs Happen
ale ustawia tę samą orientację dla całej aktywności, czy jest
jakikolwiek inny
106

Uważaj na różnicę między tym, co zwraca getConfiguration, a tym, czego chce setRequestedOrientation - oba są typu int, ale pochodzą z różnych definicji stałych.

Oto jak zablokować bieżącą orientację, pozwalając jednocześnie na obrót o 180 stopni

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
Andy Weinstein
źródło
13
Możesz preferować użycie SCREEN_ORIENTATION_USER_LANDSCAPE, ponieważ nie pozwala to na obrót o 180 stopni, jeśli użytkownik wyłączył obracanie ekranu w ustawieniach. Podobnie przy przełączaniu z powrotem do swobodnej rotacji, SCREEN_ORIENTATION_USER jest lepsza niż SCREEN_ORIENTATION_SENSOR, ponieważ ta ostatnia umożliwia swobodny obrót, nawet jeśli ustawienia zakazują.
Steve Waring
Znakomity! Należy dodać, że po przełączeniu na rekonfigurację odwróconej orientacji nie występuje. Przynajmniej na urządzeniach, na których to przetestowałem. Naprawdę ważne jest, aby wiedzieć, czy chcesz zatrzymać rekonfigurację podczas niektórych pokazów dialogowych itp.
sberezin
47

Działa to na urządzeniach z odwróconym portretem i odwróconym krajobrazem.

Zablokuj orientację:

    int orientation = getActivity().getRequestedOrientation();
    int rotation = ((WindowManager) getActivity().getSystemService(
            Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
    switch (rotation) {
    case Surface.ROTATION_0:
        orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        break;
    case Surface.ROTATION_90:
        orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        break;
    case Surface.ROTATION_180:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
        break;
    default:
        orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    }

    getActivity().setRequestedOrientation(orientation);

Odblokuj orientację:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
pstoppani
źródło
5
Uzyskaj "Returns the rotation of the screen from its "natural" orientation." źródło rotacji . Dlatego na telefonie stwierdzenie, że ROTATION_0 to portret, jest prawdopodobnie poprawne, ale na tablecie jego „naturalna” orientacja to prawdopodobnie pozioma, a ROTATION_0 powinien zwrócić poziomą zamiast pionową.
jp36
@ jp36, testowałem na Nexusie 7, który ma naturalną orientację, taką samą jak telefon. Dzięki za testowanie na większym tablecie (którego nie mam).
pstoppani
1
Jak powiedział jp36, nie działa na tabletach z naturalną orientacją poziomą!
DominicM
Jak testujemy odwrócony portret w urządzeniu?
AndyBoy
27

Wydawało mi się, że miałem podobny przypadek. Chciałem wspierać dowolną orientację, ale musiałem pozostać przy obecnej orientacji po pewnym momencie w przepływie pracy. Moje rozwiązanie brzmiało:

Przy wejściu do chronionego przepływu pracy:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

Przy wyjściu z chronionego przepływu pracy:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
stefan bachert
źródło
2
Nie dotyczy to OQ, przynajmniej na Androidzie> = 16. setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) może ustawić urządzenie w poziomie, nawet jeśli było w orientacji pionowej, podczas gdy pytanie dotyczy podanej orientacji blokowania.
greg7gkb
3
do mnie, ustawienie go na nosensor przenosi mnie z powrotem do trybu portretowego, gdybym był w trybie poziomym, zamiast tego użyłem SCREEN_ORIENTATION_LOCKED i zadziałało to dla mnie
Jimmar
1
@JiMMaR SCREEN_ORIENTATION_LOCKED to najlepszy sposób na Androida> = 18. Ale jeśli celujesz w coś niższego, to nie działa. Proponuję użyć odpowiedzi jp36 poniżej.
Patrick Boos,
23

Alternatywa dla odpowiedzi @pstoppani z obsługą tabletów (podobnie jak odpowiedź @pstoppani, będzie działać tylko na urządzeniach> 2.2)
-Testowane na Samsung Galaxy SIIIiSamsung Galaxy Tab 10.1

public static void lockOrientation(Activity activity) {
    Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = display.getRotation();
    int tempOrientation = activity.getResources().getConfiguration().orientation;
    int orientation = 0;
    switch(tempOrientation)
    {
    case Configuration.ORIENTATION_LANDSCAPE:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
            orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
        break;
    case Configuration.ORIENTATION_PORTRAIT:
        if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
            orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        else
            orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
    }
    activity.setRequestedOrientation(orientation);
}
jp36
źródło
Dzięki, to dobrze działa, ale ja nie rozumiem, dlaczego jest to, że kontrola z ||w rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90i rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270. Więc mam 2 wątpliwości :::: po pierwsze, dlaczego ROTATION_0zamiast ROTATION_180w drugim przypadku i po drugie po co sprawdzać 0 stopni z 90 a nie 180 ??
AndyBoy,
@AndyBoy ma to związek z domyślną orientacją urządzeń. Zazwyczaj telefony mają domyślną orientację pionową, co oznacza, że ​​obrót zwraca zero w przypadku orientacji pionowej, ale niektóre tablety mają domyślną orientację poziomą, co oznacza, że ​​obrót zwraca zero w przypadku orientacji poziomej. Tak więc różne ||testy obsługują dwie możliwe domyślne orientacje w oparciu o urządzenie raportujące poziomo i pionowo.
jp36
5

Oto mój kod, możesz zablokować ekran jedną z tych metod, a po zakończeniu zadania odblokować go za pomocą unlockOrientation:

/** Static methods related to device orientation. */
public class OrientationUtils {
    private OrientationUtils() {}

    /** Locks the device window in landscape mode. */
    public static void lockOrientationLandscape(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    /** Locks the device window in portrait mode. */
    public static void lockOrientationPortrait(Activity activity) {
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /** Locks the device window in actual screen mode. */
    public static void lockOrientation(Activity activity) {
        final int orientation = activity.getResources().getConfiguration().orientation;
        final int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

        // Copied from Android docs, since we don't have these values in Froyo 2.2
        int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
        int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

        // Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO
        if (!BuildVersionUtils.hasGingerbread()) {
            SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
            SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        }

        if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90){
            if (orientation == Configuration.ORIENTATION_PORTRAIT){
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
            else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        }
        else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) 
        {
            if (orientation == Configuration.ORIENTATION_PORTRAIT){
                activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            }
            else if (orientation == Configuration.ORIENTATION_LANDSCAPE){
                activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
        }
    }

    /** Unlocks the device window in user defined screen mode. */
    public static void unlockOrientation(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
    }

}
madx
źródło
0

Oto konwersja Xamarin odpowiedzi @pstoppani powyżej.

UWAGA: dotyczy fragmentu, wymień aktywność. z tym. jeśli jest używany w ramach działania.

public void LockRotation()
{
    ScreenOrientation orientation;

    var surfaceOrientation = Activity.WindowManager.DefaultDisplay.Rotation;

    switch (surfaceOrientation) {
        case SurfaceOrientation.Rotation0:
            orientation = ScreenOrientation.Portrait;
            break;
        case SurfaceOrientation.Rotation90:
            orientation = ScreenOrientation.Landscape;
            break;
        case SurfaceOrientation.Rotation180:
            orientation = ScreenOrientation.ReversePortrait;
            break;
        default:
            orientation = ScreenOrientation.ReverseLandscape;
            break;
    }

    Activity.RequestedOrientation = orientation;
}

public void UnlockRotation()
{
    Activity.RequestedOrientation = ScreenOrientation.Unspecified;
}

Nie jest to testowane, ponieważ przed użyciem było inne podejście, ale może się przydać.

WickedW
źródło
To jest ta sama odpowiedź, co pstoppani i zawiedzie na tablecie.
Tim Autin,