Como bloquear a orientação durante o tempo de execução

107

Existe uma maneira de bloquear a orientação durante o tempo de execução? Por exemplo, eu gostaria de permitir que o usuário bloqueie a tela em paisagem se o usuário estiver atualmente em paisagem e alterne a opção de menu.

Jared
fonte

Respostas:

133
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Chamado em uma atividade, irá bloqueá-lo na paisagem. Procure os outros sinalizadores na classe ActivityInfo. Você pode travá-lo de volta para retrato ou torná-lo acionado por sensor / controle deslizante.

Mais informações aqui: http://www.devx.com/wireless/Article/40792

haseman
fonte
13
Ok, obrigado. Isso funciona muito bem. Isso obterá a orientação atual. getResources (). getConfiguration (). orientação
Jared,
7
Cuidado! Você precisa diferenciar entre o que getConfiguration () retorna e o que setRequestedOrientation deseja - veja minha resposta abaixo para detalhes
Andy Weinstein
há um problema com essa abordagem. Certifique-se de ler o comentário desta resposta
Bugs Happen
mas ele define a mesma orientação para toda a atividade, há alguma outra maneira de mudarmos a orientação
silverFoxA
106

Tenha cuidado com a diferença entre o que getConfiguration retorna e o que setRequestedOrientation deseja - ambos são int, mas vêm de diferentes definições de constantes.

Veja como bloquear a orientação atual, permitindo giros de 180 graus

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
fonte
13
Você pode preferir usar SCREEN_ORIENTATION_USER_LANDSCAPE, pois isso não permite giros de 180 graus se o usuário desabilitou a rotação da tela nas configurações. Da mesma forma, ao voltar para a rotação livre, SCREEN_ORIENTATION_USER é melhor do que SCREEN_ORIENTATION_SENSOR, pois o último permite a rotação livre mesmo que as configurações indiquem o contrário.
Steve Waring
Brilhante! É preciso acrescentar que, quando você muda para a orientação reversa, a reconfiguração não ocorre. Pelo menos em dispositivos em que testei. É muito importante saber se você deseja interromper a reconfiguração durante alguns programas de diálogo, etc.
sberezin
47

Isso funciona em dispositivos com retrato reverso e paisagem reversa.

Orientação de bloqueio:

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

Orientação de desbloqueio:

   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
pstoppani
fonte
5
Obtenha a "Returns the rotation of the screen from its "natural" orientation." fonte de rotação . Portanto, em um telefone, dizer que ROTATION_0 é retrato provavelmente está correto, mas em um tablet sua orientação "natural" é provavelmente paisagem e ROTATION_0 deve retornar paisagem em vez de retrato.
jp36 de
@ jp36, testei em um Nexus 7 que tem uma orientação natural semelhante a um telefone. Obrigado por testar em um tablet maior (que eu não tenho).
pstoppani
1
Como jp36 disse, ele não funciona em tablets com orientação de paisagem natural!
DominicM
Como testamos o retrato reverso no dispositivo ??
AndyBoy
27

Parece que tive um caso semelhante. Eu queria apoiar qualquer orientação, mas precisava permanecer na orientação atual depois de um determinado ponto do fluxo de trabalho. Minha solução foi:

Na entrada do fluxo de trabalho protegido:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

Na saída do fluxo de trabalho protegido:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
stefan bachert
fonte
2
Isso não aborda o OQ, pelo menos no Android> = 16. setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) pode definir o dispositivo para paisagem mesmo se estivesse em retrato, enquanto a questão se refere à orientação de bloqueio que foi fornecida.
greg7gkb
3
para mim, configurá-lo como nosensor me leva de volta ao modo retrato se eu estivesse no modo paisagem, usei SCREEN_ORIENTATION_LOCKED e funcionou para mim
Jimmar
1
@JiMMaR SCREEN_ORIENTATION_LOCKED é a melhor maneira para Android> = 18. Mas caso você almeje algo inferior, isso não funciona. Eu sugiro usar a resposta do jp36 abaixo.
Patrick Boos
23

Alternativa para a resposta @pstoppani com suporte para tablets (como com a resposta @pstoppani, isso só funcionará em dispositivos> 2.2)
-Testado em 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);
}
jp36
fonte
Obrigado, é trabalhar bem, mas eu não entendia que por isso que é cheque com ||em rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90e com rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270. Então eu tenho 2 dúvidas :::: primeiro, por que ao ROTATION_0invés de ROTATION_180no segundo caso e outra por que marcar 0 grau com 90 não 180 ??
AndyBoy
@AndyBoy tem a ver com a orientação padrão dos dispositivos. Normalmente, os telefones têm uma orientação padrão de retrato, o que significa que a rotação retorna zero para retrato, mas alguns tablets têm um padrão de paisagem, o que significa que a rotação retorna zero para paisagem. Portanto, as diferentes ||verificações estão lidando com as duas orientações padrão possíveis com base no dispositivo relatando paisagem versus retrato.
jp36 de
5

Aqui está o meu código, você pode bloquear sua tela com um desses métodos e, uma vez concluída a tarefa, desbloqueá-la com 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
fonte
0

Aqui está a conversão do Xamarin da resposta de @pstoppani acima.

NOTA: isto é para um fragmento, substitua a atividade. com isso. se usado em uma atividade.

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

Isso não foi testado com uma abordagem diferente antes de ser usado, mas pode ser útil.

WickedW
fonte
Essa é a mesma resposta que a de pstoppani e falhará em um tablet.
Tim Autin