Como desabilito a alteração de orientação no Android?

287

Eu tenho um aplicativo que gostaria de usar no modo retrato, por isso defini android: screenOrientation = "portrait" no XML do manifesto. Isso funciona bem para o HTC Magic telefone (e evita alterações de orientação em outros telefones também).

Mas tenho um problema com o telefone HTC G1 quando abro o teclado QWERTY de hardware (não o teclado virtual). Minha atividade permanece no modo retrato, mas parece ser reiniciada e perde todos os seus estados. Isso não acontece com o HTC Hero versão .

Meu aplicativo é muito grande, então não quero que ele seja reiniciado e perca todos os seus estados quando o teclado for aberto. Como posso evitar isso?

Vidar Vestnes
fonte

Respostas:

317

Atualização de abril de 2013: não faça isso. Não foi uma boa ideia em 2009, quando eu respondi a pergunta, e realmente não é uma boa ideia agora. Veja esta resposta por hackbod por razões:

Evite recarregar atividades com o asynctask na mudança de orientação no android

Adicione android:configChanges="keyboardHidden|orientation"ao seu AndroidManifest.xml. Isso informa ao sistema quais alterações de configuração você irá gerenciar - nesse caso, sem fazer nada.

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

Consulte Referência de desenvolvedor configChanges para obter mais detalhes.

No entanto, seu aplicativo pode ser interrompido a qualquer momento, por exemplo, por uma ligação telefônica, portanto, você deve adicionar um código para salvar o estado do seu aplicativo quando ele estiver em pausa.

Atualização: no Android 3.2, você também precisa adicionar "screenSize":

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

Do guia do desenvolvedor Manipulando a alteração de configuração você mesmo

Cuidado: a partir do Android 3.2 (API nível 13), o "tamanho da tela" também muda quando o dispositivo alterna entre a orientação retrato e paisagem. Portanto, se você deseja impedir a reinicialização do tempo de execução devido à alteração da orientação ao desenvolver para o nível 13 da API ou superior (conforme declarado pelos atributos minSdkVersion e targetSdkVersion), inclua o valor "screenSize", além do valor da "orientação". Ou seja, você deve declarar android:configChanges="orientation|screenSize". No entanto, se o seu aplicativo atingir a API de nível 12 ou inferior, sua atividade sempre lida com essa alteração de configuração (ela não reinicia sua atividade, mesmo quando executada em um dispositivo Android 3.2 ou superior).

Intrications
fonte
36
Apenas para adicionar isso e ser realmente explícito, o Android pode matar seu aplicativo sem piedade a qualquer momento, independentemente das alterações de orientação; portanto, você deve usar onPause () e onSaveInstanceState () para salvar o estado, não importa o que aconteça.
Eric Mill
A atualização 3.2 foi muito útil e foi o que estava me bloqueando. Não sabia por que meu manipulador onConfigurationChanged não estava disparando e foi isso. Obrigado!
Sweetlilmre
o terceiro param - screenSize não pode ser encontrado no 2.3.x, devo mudar para screenLayout?
deadfish
2
@ Lumma Não, "screenSize" é necessário apenas para o Android 3.2 e mais recente. Qual nível de API você está segmentando? Acho que você só precisará adicioná-lo se tiver como alvo o nível 13 ou superior. Vou atualizar a resposta para esclarecer.
Intrications
1
Caso seja útil para outras pessoas, eu encontrei vocês <... android: configChanges = "guidance" ...> substituindo alterações e <... android: screenOrientation = "portrait" ...> para defina o padrão.
Sogger
97

Você precisa modificar o AndroidManifest.xml como as Intrications (anteriormente Ashton) mencionadas e garantir que a atividade lide com o evento onConfigurationChanged como desejar. É assim que deve parecer:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
ubershmekel
fonte
Como observado por Dmitry Zaitsev, é melhor colocar o setRequestedOrientation()in onCreate().
Timmmm 11/09/12
3
Não é onConfigurationChanged()chamado antesonCreate() se definir a orientação antes de definir o contentViews no oncreate é uma abordagem melhor , definir a configuração onde ele pertence também é mais limpo, portanto essa resposta ainda permanece boa.
Samuel
39

Eu sempre achei que você precisava dos dois

android:screenOrientation="nosensor" android:configChanges="keyboardHidden|orientation"
m00sey
fonte
22

Como dito, defina android:configChangessua Atividade (no arquivo de manifesto) para keyboardHidden|orientatione depois:

1) Substituir onConfigurationChanged()

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

2) Adicione esta linha às suas atividades onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

É melhor do que adicionar a mesma linha onConfigurationChanged, porque seu aplicativo passará para o modo retrato e depois voltará para o modo paisagem (isso acontecerá apenas uma vez, mas é irritante).

Além disso, você pode definir android:screenOrientation="nosensor"sua atividade (no manifesto). Mas, dessa maneira, você não consegue lidar com as alterações de orientação.

Dmitry Zaytsev
fonte
O que devo fazer se quiser evitar a recriação da atividade durante a rotação, mas desejo permitir que o usuário bloqueie a orientação através das configurações do sistema operacional?
android developer
@androiddeveloper que uma questão separada, que já tem uma resposta: stackoverflow.com/a/14771495/926907
Dmitry Zaytsev
Seu link é sobre alterar o conteúdo sozinho quando a configuração for alterada, mas desejo evitar a rotação da atividade (para que ela fique exatamente da maneira que parece) caso o usuário tenha optado por bloquear a orientação pelos SOs configurações (disponíveis em alguns dispositivos nas configurações rápidas, na gaveta de notificações).
desenvolvedor android
@androiddeveloper ah, acho que entendi. Dê uma olhada neste link: developer.android.com/reference/android/… De acordo com os documentos, a orientação padrão já deve levar em consideração a preferência do usuário. Se não for esse o caso, suspeito que seja um comportamento específico do SO. Eu ficaria feliz em ouvir sobre os seus resultados - agora eu também estou interessado nele :)
Dmitry Zaytsev
Eu sei que o padrão manipulará as preferências do usuário, mas também recria a atividade quando você gira a tela, o que é algo que eu não quero ter.
desenvolvedor android
20

Usa isto..

    android:screenOrientation="portrait"
Muhammad Aamir Ali
fonte
13

No método OnCreate da sua atividade, use este código:

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

Agora sua orientação será configurada para retrato e nunca será alterada.

Numenor
fonte
4
Com isso, você não impede o reinício da atividade sempre que a configuração da orientação é alterada.
AxeEffect
Além disso, isso não funciona se você inserir a atividade de uma atividade anterior na orientação paisagem.
W3bshark 15/0218
10

No arquivo AndroidManifest.xml, para cada atividade que você deseja bloquear, adicione a última screenOrientationlinha:

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

Ou android: screenOrientation = "paisagem" .

Gil Allen
fonte
8

No seu arquivo androidmanifest.xml :

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

ou

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Jorgesys
fonte
6

Para bloquear a tela por código, você deve usar a rotação real da tela (0, 90, 180, 270) e saber a posição natural dela; em um smartphone, a posição natural será retrato e em um tablet, será paisagem.

Aqui está o código (métodos de bloqueio e desbloqueio), ele foi testado em alguns dispositivos (smartphones e tablets) e funciona muito bem.

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
fonte
que paramater deve ser passado como atividade?
WISHY
A atividade que chama o método para bloquear / desbloquear sua orientação. Esse é um método público de utilidade estática a ser chamado de diferentes atividades.
PoOk
1
Funciona muito bem, mas, sério, Android, por que temos que fazer tudo isso apenas para orientação da tela de bloqueio? !!!
Cocorico
sim. Este bloqueia a orientação como fazemos no manifesto. Isso impedirá que o onConfigurationChanged seja mais invocado. Existe um método que bloqueie a interface do usuário para paisagem e ainda invoque o onConfigurationChanged. Assim como o aplicativo da câmera no Android faz
Ajith Memana 11/11
Há uma bandeira SCREEN_ORIENTATION_LOCKED on SDK 18+ que parece trabalho, mas você ainda gostaria de usar o código acima para suportar todos os dispositivos
DominicM
2

No Visual Studio Xamarin:

  1. Adicionar:

using Android.Content.PM; para sua lista de namespace de atividades.

  1. Adicionar:

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

como um atributo para sua classe, assim:

[Activity(ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : Activity
{...}
Roy Doron
fonte
Esta pergunta está perguntando sobre o Android, não o Xamarin. Android
Trevor Hart
1

Adicionar

android:configChanges="keyboardHidden|orientation|screenSize" 

para o seu manifesto.

saurabh
fonte
dentro de sua tag <atividade>
Ege Kuzubasioglu
0

Observe que nenhum dos métodos parece funcionar agora!

No Android Studio 1, uma maneira simples é adicionar android:screenOrientation="nosensor" .

Isso efetivamente bloqueia a orientação da tela.

cefálico
fonte