Como detectar mudança de orientação no layout no Android?

110

Acabei de implementar um recurso de mudança de orientação - por exemplo, quando o layout muda de retrato para paisagem (ou vice-versa). Como posso detectar quando o evento de mudança de orientação terminou.

O OrientationEventListenernão funcionou. Como posso obter notificações sobre eventos de mudança de orientação de layout?

user403015
fonte
No meu caso, onCreate () foi chamado quando a orientação muda.
Josiel Novaes

Respostas:

292

Use o método onConfigurationChanged de Activity. Veja o seguinte código:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Você também tem que editar o apropriado elemento em seu arquivo de manifesto para incluir o android: configChanges Basta ver o código abaixo:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

NOTA: com Android 3.2 (API de nível 13) ou superior, o "tamanho da tela" também muda quando o dispositivo alterna entre a orientação retrato e paisagem. Portanto, se você quiser evitar reinicializações de tempo de execução devido à mudança de orientação ao desenvolver para API de nível 13 ou superior, você deve declarar android: configChanges = "idance | screenSize "para API de nível 13 ou superior .

Espero que isso ajude você ... :)

Dinesh Sharma
fonte
3
Isso é bom, mas não carrega o layout xml na pasta layout-land; ele usa os arquivos de layout xml retrato.
Programador
22
Aztec Coder, ao incluir "android: configChanges =" orientação ", você está declarando que tratará da mudança de orientação, o que significa que sua atividade não será recriada quando você mudar para paisagem. Em vez disso, onConfigurationChanged é chamado. Se for indesejado , você poderia usar uma variável para lembrar a orientação da sua atividade e cada vez que você fizer uma pausa (por exemplo) para verificar se a orientação ainda é a mesma.
Elena
14
Se você estiver desenvolvendo para API de nível 13 (3.2) ou superior, deve especificar android: configChanges = "idance | screenSize ", caso contrário onConfigurationChanged não será chamado: developer.android.com/guide/topics/resources/…
Arne
1
Olá, estou criando meu aplicativo com API 10 (Android 2.3.3). E ele reconhece a orientação perfeitamente quando eu uso o android: configChanges = "idance | keyboardHidden ". Mas meu Nexus S, que executa o Android 4.1.2, não detecta a mudança de orientação. O que devo fazer?
Karthik Andhamil
2
use android: configChanges = "idance | screenSize "em vez de android: configChanges =" customization | keyboardHidden "em seu arquivo de manifesto e verifique ... !!!
Dinesh Sharma
15

Para carregar o layout na pasta layout-land significa que você tem dois layouts separados, então você tem que fazer setContentViewno onConfigurationChangedmétodo.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Se você tiver apenas um layout, não será necessário fazer setContentView neste método. simplesmente

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
fonte
19
Em vez de substituir, basta usar layout / main.xml e layout-land / main.xml.
Jared Burrows
@JaredBurrows: Consulte stackoverflow.com/questions/23789605/…
B. Clay Shannon
Eu queria detectar que minha atividade foi encerrada devido a uma rotação da tela. Implementei o onConfigurationChanged(Configuration newConfig)método (como nesta resposta), mas em vez de manipulá-lo sozinho, defini um sinalizador booleano e chamei o recreate()método para que o Android recriasse a atividade em seu modo normal.
atordoado em
Um problema com o recreate()método é que ele faz com que a tela pisque em preto brevemente. Por esta razão, usei outra abordagem: (1) salvar a largura da tela no onCreate(...), (2) comparar a largura da tela salva com a largura da tela atual em qualquer método de ciclo de vida quando a atividade estiver sendo encerrada (por exemplo onSaveInstanceState(...)).
atordoado em
13

Só queria mostrar a você uma maneira de salvar todo o seu pacote após onConfigurationChanged:

Crie um novo pacote logo após a sua aula:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Em seguida, depois de "protected void onCreate" adicione isto:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Se você adicionar isso, todas as suas classes criadas em MainActivity serão salvas.

Mas a melhor maneira é adicionar isso ao seu AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
fonte
7
Isso é enganoso. Implementar onConfigurationChanged()faz com que seu instanceState não seja destruído quando a orientação muda, então você não precisa salvá-lo. Você pode querer salvá-lo para outros eventos no ciclo de vida da atividade, mas não sei.
Izzy
5

use este método

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

E não se esqueça de adicionar isso em seu Androidmainfest.xml

android:configChanges="orientation|screenSize"

como isso

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>
Sai Gopi Me
fonte
2

Substituir o método da atividade onConfigurationChanged

Flavio
fonte
Gostaria de salientar que, sem a seguinte linha dentro da tag <activity> no manifesto, a chamada de retorno onConfigurationChanged () nem seria acionada. android: configChanges = "orientação"
Sreekanth Karumanaghat
1

Só quero propor outra alternativa que vai preocupar alguns de vocês, de fato, conforme explicado acima:

android:configChanges="orientation|keyboardHidden" 

implica que declaramos explicitamente o layout a ser injetado.

Caso queiramos manter a injeção automática graças às pastas layout-land e layout. Tudo que você precisa fazer é adicioná-lo ao onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Aqui, exibimos ou não a barra de ação dependendo da orientação do telefone

Z3nk
fonte
0

Crie uma instância de OrientationEventListenerclasse e ative-a.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
fonte
2
Por favor, não vandalize sua resposta. Se você deseja excluí-lo, você pode encontrar o botão de exclusão no canto inferior esquerdo da sua resposta.
CalvT
0

Se a resposta aceita não funcionar para você, certifique-se de não definir no arquivo de manifesto:

android:screenOrientation="portrait"

Qual é o meu caso.

Jiyeh
fonte
0

No caso de ser útil para algum desenvolvedor mais recente, porque não foi especificado acima. Só para ser bem explícito:

Você precisa de duas coisas se estiver usando onConfigurationChanged :

  1. Um onConfigurationChangedmétodo em sua classe de atividade

  2. Especifique em seu manifesto quais mudanças de configuração serão tratadas por seu onConfigurationChangedmétodo

O snippet de manifesto nas respostas acima, embora sem dúvida correto para o aplicativo específico ao qual o manifesto pertence, NÃO é exatamente o que você precisa adicionar em seu manifesto para acionar o método onConfigurationChanged em sua classe de atividade. ou seja, a entrada do manifesto abaixo pode não ser correta para o seu aplicativo.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

Na entrada de manifesto acima, há várias ações do Android para as android:configChanges=""quais podem acionar onCreate em seu ciclo de vida de atividade.

Isso é muito importante - Os NÃO especificados no manifesto são os que acionam o seu onCreate e os especificados no manifesto são os que acionam o seu onConfigurationChangedmétodo na classe de atividade.

Portanto, você precisa identificar quais mudanças de configuração você precisa controlar. Para Android Encyclopedically Challenged como eu, usei as dicas rápidas pop-out no Android Studio e adicionei quase todas as opções de configuração possíveis. Listar tudo isso basicamente dizia que eu trataria de tudo e onCreate nunca seria chamado devido às configurações.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Obviamente, não quero lidar com tudo, então comecei a eliminar as opções acima, uma de cada vez. Reconstruir e testar meu aplicativo após cada remoção.

Outro ponto importante : Se houver apenas uma opção de configuração sendo tratada automaticamente que aciona seu onCreate (você não a tem listado em seu manifesto acima), então aparecerá como onConfigurationChangedse não estivesse funcionando. Você deve colocar todos os relevantes em seu manifesto.

Eu terminei com 3 que estavam ativando onCreate originalmente, então testei em um S10 + e ainda estava recebendo o onCreate, então tive que fazer meu exercício de eliminação novamente e também precisava do |screenSize. Portanto, teste em uma seleção de plataformas.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Minha sugestão, embora eu tenha certeza de que alguém pode abrir buracos nisso:

  1. Adicione seu onConfigurationChangedmétodo em sua classe de atividade com um TOAST ou LOG ​​para que você possa ver quando está funcionando.

  2. Adicione todas as opções de configuração possíveis ao seu manifesto.

  3. Confirme se seu onConfigurationChangedmétodo está funcionando testando seu aplicativo.

  4. Remova cada opção de configuração de seu arquivo de manifesto, uma de cada vez, testando seu aplicativo após cada uma.

  5. Teste na maior variedade possível de dispositivos.

  6. Não copie / cole meu snippet acima em seu arquivo de manifesto. As atualizações do Android mudam a lista, portanto, use as dicas pop-out do Android Studio para ter certeza de obter todas elas.

Espero que isso economize algum tempo.

Meu onConfigurationChangedmétodo apenas para informações abaixo. onConfigurationChangedé chamado no ciclo de vida após a nova orientação estar disponível, mas antes que a IU seja recriada. Portanto, meu primeiro ifpara verificar se a orientação funciona corretamente e, em seguida, o segundo aninhado ifpara ver a visibilidade do meu UI ImageView também funciona corretamente.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }
DMur
fonte
0

para implementação Kotilin na forma mais simples - dispara apenas quando a tela muda de retrato <--> paisagem se você precisar de um dispositivo de detecção de giro (180 graus), você precisará acessar os valores do sensor de gravidade

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}
alpha911
fonte