Gostaria que os tablets pudessem ser exibidos em retrato e paisagem (sw600dp ou superior), mas os telefones devem ser restritos apenas a retrato. Não consigo encontrar uma maneira de escolher uma orientação condicionalmente. Alguma sugestão?
Gostaria que os tablets pudessem ser exibidos em retrato e paisagem (sw600dp ou superior), mas os telefones devem ser restritos apenas a retrato. Não consigo encontrar uma maneira de escolher uma orientação condicionalmente. Alguma sugestão?
Respostas:
Aqui está uma boa maneira de usar qualificadores de recursos e tamanho .
Coloque esse recurso bool em res / values como bools.xml ou o que for (nomes de arquivos não importam aqui):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Coloque este em res / values-sw600dp e res / values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Veja esta resposta suplementar para obter ajuda sobre como adicionar esses diretórios e arquivos no Android Studio.
Em seguida, no método onCreate de suas atividades, você pode fazer isso:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Os dispositivos que são mais do que 600 dp na direcção da largura mais pequena, ou x larga em dispositivos de pré-Android 3.2 (comprimidos, basicamente) irá comportar-se como o normal, baseado no sensor e rotação bloqueado pelo utilizador, etc . Todo o resto (telefones, basicamente) será apenas retrato.
xlarge
também ou posso usar sw600dp
? Provavelmente, não há tablets executando <3,2 nos dias de hoje.
onCreate()
. Quando mudei a chamada para setRequestedOrientation()
uma posição diferente no tempo e no contexto, o reinício não aconteceu mais.
Você pode tentar dessa maneira primeiro obter o tamanho da tela do dispositivo
if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
Toast.makeText(this, "Large screen",Toast.LENGTH_LONG).show();
}
else if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
Toast.makeText(this, "Normal sized screen" , Toast.LENGTH_LONG).show();
}
else if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
Toast.makeText(this, "Small sized screen" , Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(this, "Screen size is neither large, normal or small" , Toast.LENGTH_LONG).show();
}
e depois defina a orientação de acordo com
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Configuration
fornece screenLayout
informações - DPI. Considerando que a questão está relacionada ao tamanho da tela do dispositivo físico - telefone VS tablet. Ou seja, você pode ter um Configuration.SCREENLAYOUT_SIZE_NORMAL
e seria um tablet MDPI.
Você pode executar as seguintes etapas no Android Studio para adicionar os diretórios res/values-sw600dp
e res/values-large
com seusbools.xml
arquivos.
Primeiro, na guia Projeto, selecione o filtro Projeto (em vez do Android) no navegador.
Em seguida, clique com o botão direito do mouse no app/src/main/res
diretório Escolha Novo > Diretório de Recursos do Android .
Selecione Menor largura da tela e pressione o botão >> .
Digite 600
para a menor largura da tela. O nome do diretório será gerado automaticamente. Diga OK.
Em seguida, clique com o botão direito do mouse no values-sw600dp
arquivo recém-criado . Escolha Novo > Arquivo de Recurso Valores . Tipobools
para o nome.
A adição de um values-large
diretório é necessária apenas se você estiver suportando o pré-Android 3.2 (nível 13 da API). Caso contrário, você pode pular esta etapa. O values-large
diretório corresponde a values-sw600dp
. ( values-xlarge
corresponde a values-sw720dp
.)
Para criar o values-large
diretório, siga as mesmas etapas acima, mas, neste caso, escolha Tamanho em vez de Menor largura da tela. Selecione grande . O nome do diretório será gerado automaticamente.
Clique com o botão direito do mouse no diretório como antes para criar o bools.xml
arquivo.
Aqui está como eu fiz isso (inspirado em http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):
No AndroidManifest.xml, para cada atividade que você deseja alterar entre retrato e paisagem (adicione screenSize - você não costumava precisar disso!). Você não precisa definir uma orientação de tela aqui. :
android:configChanges="keyboardHidden|orientation|screenSize"
Métodos para adicionar em cada atividade:
public static boolean isXLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
e: (se você não substituir esse método, o aplicativo chamará onCreate () ao alterar as orientações)
@Override
public void onConfigurationChanged (Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (!isXLargeScreen(getApplicationContext()) ) {
return; //keep in portrait mode if a phone
}
//I set background images for landscape and portrait here
}
Em onCreate () de cada atividade:
if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else {
//I set background images here depending on portrait or landscape orientation
}
A única coisa que não consigo entender é como fazer com que o aplicativo altere os arquivos de layout ao mudar de paisagem para retrato ou vice-versa. Presumo que a resposta esteja fazendo algo semelhante ao que o link acima faz, mas não consegui que isso funcionasse para mim - ele excluiu todos os meus dados. Mas se você tiver um aplicativo simples o suficiente para ter o mesmo arquivo de layout para retrato e paisagem, isso funcionará.
Seguindo a resposta de Ginny , acho que a maneira mais confiável de fazer isso é a seguinte:
Conforme descrito aqui , coloque um booleano nos recursos sw600dp. Ele deve ter o prefixo sw, caso contrário não funcionará corretamente:
em res / values-sw600dp / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
em res / values / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">false</bool>
</resources>
Em seguida, crie um método para recuperar esse booleano:
public class ViewUtils {
public static boolean isTablet(Context context){
return context.getResources().getBoolean(R.bool.isTablet);
}
}
E uma atividade base a ser estendida das atividades em que você deseja esse comportamento:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!ViewUtils.isTablet(this)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Portanto, cada atividade estenderia BaseActivity:
public class LoginActivity extends BaseActivity //....
Importante : mesmo que você estenda de BaseActivity
, você deve adicionar a linha android:configChanges="orientation|screenSize"
a cada Activity
no seu AndroidManifest.xml:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
Bem, isso é um pouco tarde, mas, aqui está uma solução Somente XML, mas uma hack, que não recria uma atividade como setRequestedOrientation
faz se for necessário alterar a orientação:
Após a resposta aceita , estou adicionando o arquivo kotlin com a solução espero que ajude alguém
Coloque esse recurso bool res/values
como bools.xml ou o que for (nomes de arquivos não importam aqui):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Coloque este aqui res/values-sw600dp
e res/values-sw600dp-land
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Em seguida, adicione-o nas linhas abaixo da sua atividade ou fragmentidade
class MyActivity : Activity() {
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
if (resources.getBoolean(R.bool.portrait_only)) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
super.onCreate(savedInstanceState)
}
@SuppressLint("SourceLockedOrientationActivity")
override fun onConfigurationChanged(newConfig: Configuration) {
if (resources.getBoolean(R.bool.portrait_only)) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
super.onConfigurationChanged(newConfig)
}
}
Outras soluções não funcionaram para mim. Eu ainda tinha algum problema de orientação estranho com diálogos e questões de recreação. Minha solução foi estender a Atividade, forçando-a como retrato em manifesto.
Exemplo:
public class MainActivityPhone extends MainActivity {}
manifest.xml:
<activity
android:screenOrientation="portrait"
android:name=".MainActivityPhone"
android:theme="@style/AppTheme.NoActionBar" />
na atividade de tela inicial:
Intent i = null;
boolean isTablet = getResources().getBoolean(R.bool.is_tablet);
if (!isTablet)
i = new Intent(this, MainActivityPhone.class);
else
i = new Intent(this, MainActivity.class);
startActivity(i);
Velha pergunta eu sei. Para executar seu aplicativo sempre no modo retrato, mesmo quando a orientação pode ser ou é trocada, etc. (por exemplo, em tablets), projetei essa função que é usada para definir o dispositivo na orientação correta sem a necessidade de saber como o retrato e a paisagem recursos estão organizados no dispositivo.
private void initActivityScreenOrientPortrait()
{
// Avoid screen rotations (use the manifests android:screenOrientation setting)
// Set this to nosensor or potrait
// Set window fullscreen
this.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
DisplayMetrics metrics = new DisplayMetrics();
this.activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Test if it is VISUAL in portrait mode by simply checking it's size
boolean bIsVisualPortrait = ( metrics.heightPixels >= metrics.widthPixels );
if( !bIsVisualPortrait )
{
// Swap the orientation to match the VISUAL portrait mode
if( this.activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT )
{ this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }
else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); }
}
else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); }
}
Funciona como um encanto!
AVISO: Altere de acordo this.activity
com sua atividade ou adicione-o à atividade principal e remova this.activity
;-)
Se você quiser fazer o oposto, deve alterar o código para paisagem (mas acho que fica claro como fazer isso).
Infelizmente, usando o método setRequestedOrientation (...) fará com que a atividade reinicie; portanto, mesmo que você chame isso no método onCreate, ele passará pelo ciclo de vida da atividade e, em seguida, recriará a mesma atividade na orientação solicitada. Portanto, na resposta de @Brian Christensen, você deve considerar que o código de atividade pode ser chamado duas vezes, isso pode ter efeitos negativos (não apenas visuais, mas também em solicitações de rede, análises, etc.).
Além disso, definir o atributo configChanges no manifesto é, na minha opinião, uma grande desvantagem, o que pode levar um enorme custo de refatoração. Os desenvolvedores do Android não recomendam alterar esse atributo .
Por fim, tentar definir a ScreenOrientation de alguma forma diferente (para evitar o problema de reinicialização) é impossível, estaticamente impossível devido ao manifesto estático que não pode ser alterado, programaticamente, só é possível chamar esse método na atividade já iniciada.
Resumo: na minha opinião, a sugestão de @Brian Christensen é a melhor opção, mas lembre-se do problema de reiniciar a atividade.
layout-land
internares
.