Come bloccare l'orientamento durante il runtime


107

C'è un modo per bloccare l'orientamento durante il runtime? Ad esempio, vorrei consentire all'utente di bloccare lo schermo in orizzontale se l'utente attualmente è in orizzontale e attivare l'opzione di menu.

Risposte:


133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Chiamato in un'attività, lo bloccherà in orizzontale. Cerca gli altri flag nella classe ActivityInfo. Puoi bloccarlo di nuovo in verticale o renderlo guidato da sensore / cursore.

Maggiori informazioni qui: http://www.devx.com/wireless/Article/40792


13
Ok grazie. Funziona alla grande. Questo otterrà l'orientamento attuale. getResources (). getConfiguration (). Orientamento
Jared

7
! attento Devi distinguere tra cosa restituisce getConfiguration () e cosa vuole setRequestedOrientation - vedi la mia risposta sotto per i dettagli
Andy Weinstein

c'è un problema con questo approccio. Assicurati di leggere il commento di questa risposta
Bugs Happen

ma imposta lo stesso orientamento per tutte le attività, c'è un altro modo in cui possiamo cambiare l'orientamento
silverFoxA

106

Fai attenzione alla differenza tra ciò che getConfiguration restituisce e ciò che setRequestedOrientation vuole: sono entrambi int, ma provengono da definizioni di costanti diverse.

Ecco come bloccare l'orientamento corrente, consentendo al contempo ribaltamenti di 180 gradi

int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
else {
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}

13
Potresti preferire utilizzare SCREEN_ORIENTATION_USER_LANDSCAPE in quanto ciò non consente i ribaltamenti di 180 gradi se l'utente ha disabilitato la rotazione dello schermo nelle impostazioni. Allo stesso modo, quando si torna alla rotazione libera, SCREEN_ORIENTATION_USER è migliore di SCREEN_ORIENTATION_SENSOR poiché quest'ultimo consente la rotazione libera anche se le impostazioni dicono di non farlo.
Steve Waring

Brillante! È necessario aggiungerlo quando si passa alla riconfigurazione dell'orientamento inverso. Almeno sui dispositivi su cui l'ho testato. È molto importante sapere se si desidera interrompere la riconfigurazione durante alcuni spettacoli di dialogo, ecc.
sberezin

47

Funziona su dispositivi con ritratto inverso e paesaggio inverso.

Blocca l'orientamento:

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

Sblocca l'orientamento:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

5
Ottieni "Returns the rotation of the screen from its "natural" orientation." fonte di rotazione . Quindi su un telefono che dice che ROTATION_0 è verticale è probabile che sia corretto, ma su un tablet il suo orientamento "naturale" è probabilmente orizzontale e ROTATION_0 dovrebbe restituire orizzontale anziché verticale.
jp36

@ jp36, ho provato su un Nexus 7 che ha un orientamento naturale che è lo stesso di un telefono. Grazie per aver provato su un tablet più grande (che non ho).
pstoppani

1
Come ha detto jp36, non funziona su tablet con un orientamento orizzontale naturale!
DominicM

Come testiamo il ritratto inverso nel dispositivo?
AndyBoy

27

Mi sembrava di avere un caso simile. Volevo supportare qualsiasi orientamento, ma avevo bisogno di rimanere nell'orientamento corrente dopo un certo punto del flusso di lavoro. La mia soluzione era:

All'ingresso del flusso di lavoro protetto:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

All'uscita dal flusso di lavoro protetto:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

2
Questo non risolve l'OQ, almeno su Android> = 16. setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) potrebbe impostare il dispositivo in orizzontale anche se era in verticale, mentre la domanda si riferisce all'orientamento di blocco che è stato dato.
greg7gkb

3
per me, impostarlo su nosensor mi riporta alla modalità verticale se ero in orizzontale ho usato invece SCREEN_ORIENTATION_LOCKED e ha funzionato per me
Jimmar

1
@JiMMaR SCREEN_ORIENTATION_LOCKED è il modo migliore per Android> = 18. Ma se scegli come target qualcosa di più basso, non funziona. Suggerisco di utilizzare la risposta di jp36 di seguito.
Patrick Boos

23

Alternativa alla risposta @pstoppani con supporto per tablet (come con la risposta @pstoppani, funzionerà solo su dispositivi> 2.2)
-Testato su Samsung Galaxy SIIIeSamsung 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);
}

Grazie, funziona bene ma non ho capito perché è ||in rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90e con rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270. Quindi ho 2 dubbi :::: primo, perché ROTATION_0invece che ROTATION_180nel secondo caso e un altro perché controllare 0 gradi con 90 non 180 ??
AndyBoy

@ AnddyBoy ha a che fare con l'orientamento predefinito dei dispositivi. In genere i telefoni hanno un orientamento predefinito verticale, il che significa che la rotazione restituisce zero per verticale, ma alcuni tablet hanno un orientamento predefinito orizzontale, il che significa che la rotazione restituisce zero per il paesaggio. Quindi i diversi ||controlli gestiscono i due possibili orientamenti predefiniti basati sul dispositivo che riporta il paesaggio rispetto al ritratto.
jp36

5

Ecco il mio codice, potresti bloccare con uno di questi metodi il tuo schermo e una volta terminata l'attività sbloccarlo con 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);
    }

}

0

Ecco la conversione Xamarin della risposta di @pstoppani sopra.

NOTA: questo è per un frammento, sostituire l' attività. con questo. se utilizzato all'interno di un'attività.

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

Questo non è stato testato in quanto è andato con un approccio diverso prima di usarlo, ma potrebbe essere utile.


Questa è la stessa risposta di pstoppani e non funzionerà su un tablet.
Tim Autin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.