Je souhaite que les tablettes puissent être affichées en portrait et en paysage (sw600dp ou supérieur), mais que les téléphones soient limités à portrait. Je ne trouve aucun moyen de choisir conditionnellement une orientation. Aucune suggestion?
Voici un bon moyen d'utiliser ressources _ et qualificateurs de taille .
Mettez cette ressource bool dans res/values sous la forme bools.xml ou autre (les noms de fichiers n’importent pas ici):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Mettez celui-ci dans res/values-sw600dp et res/values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Voir cette réponse supplémentaire _ pour obtenir de l'aide sur l'ajout de ces répertoires et fichiers dans Android Studio.
Ensuite, dans la méthode onCreate de vos activités, vous pouvez le faire:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Les appareils de plus de 600 dp dans le sens de la largeur le plus petit ou x-large sur les appareils antérieurs à Android 3.2 (essentiellement les tablettes) se comporteront comme d'habitude, basé sur le capteur et la rotation verrouillée par l'utilisateur, etc. . Tout le reste (les téléphones, à peu près) ne sera que portrait.
Vous pouvez essayer de cette façon d'abord obtenir la taille de l'écran de l'appareil
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();
}
puis définir l'orientation en fonction de celle
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Voici comment je l'ai fait (inspiré par http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):
Dans AndroidManifest.xml, pour chaque activité que vous souhaitez pouvoir basculer entre portrait et paysage (assurez-vous d'ajouter screenSize - vous n'en aviez pas besoin auparavant!). Vous n'avez pas besoin de définir l'orientation de l'écran ici. :
Android:configChanges="keyboardHidden|orientation|screenSize"
Méthodes à ajouter à chaque activité:
public static boolean isXLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
et: (si vous ne remplacez pas cette méthode, l'application appellera onCreate () lors du changement d'orientations)
@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
}
Dans onCreate () de chaque activité:
if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else {
//I set background images here depending on portrait or landscape orientation
}
La seule chose que je n'arrive pas à comprendre, c'est comment faire en sorte que l'application modifie les fichiers de présentation lors du passage de paysage à portrait ou vice versa. Je suppose que la réponse consiste à faire quelque chose de similaire à ce que fait le lien ci-dessus, mais je ne pouvais pas le faire fonctionner pour moi - cela supprimait toutes mes données. Mais si vous avez une application assez simple et que vous avez le même fichier de présentation pour portrait et paysage, cela devrait fonctionner.
Vous pouvez effectuer les étapes suivantes dans Android Studio pour ajouter les répertoires res/values-sw600dp
et res/values-large
à leurs fichiers bools.xml
.
Tout d'abord, dans l'onglet Projet, sélectionnez le filtre Projet (plutôt qu'Android) dans le navigateur.
Puis cliquez avec le bouton droit sur le répertoire app/src/main/res
. Choisissez Nouveau> Répertoire des ressources Android.
Sélectionnez Largeur d'écran la plus petite, puis appuyez sur le bouton >>.
Tapez 600
pour la plus petite largeur d'écran. Le nom du répertoire sera généré automatiquement. Dis OK.
Cliquez ensuite avec le bouton droit sur le fichier values-sw600dp
nouvellement créé. Choisissez Nouveau> Fichier de ressources Values . Tapez bools
pour le nom.
L'ajout d'un répertoire values-large
n'est nécessaire que si vous prenez en charge la version antérieure à Android 3.2 (API de niveau 13). Sinon, vous pouvez ignorer cette étape. Le répertoire values-large
correspond à values-sw600dp
. (values-xlarge
correspond à values-sw720dp
.)
Pour créer le répertoire values-large
, suivez les mêmes étapes que ci-dessus, mais dans ce cas, choisissez Taille plutôt que Largeur d'écran la plus petite. Sélectionnez Large. Le nom du répertoire sera généré automatiquement.
Cliquez avec le bouton droit sur le répertoire comme précédemment pour créer le fichier bools.xml
.
Après réponse de Ginny , je pense que le moyen le plus fiable de le faire est le suivant:
Comme décrit ici , mettez un booléen dans les ressources sw600dp. Il doit avoir le préfixe sw sinon cela ne fonctionnera pas correctement:
dans res/values-sw600dp/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
dans res/values / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">false</bool>
</resources>
Créez ensuite une méthode pour récupérer ce booléen:
public class ViewUtils {
public static boolean isTablet(Context context){
return context.getResources().getBoolean(R.bool.isTablet);
}
}
Et une activité de base à étendre des activités pour lesquelles vous souhaitez ce comportement:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!ViewUtils.isTablet(this)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Ainsi, chaque activité étendrait BaseActivity:
public class LoginActivity extends BaseActivity //....
Important: même si vous prolongez de BaseActivity
, vous devez ajouter la ligne Android:configChanges="orientation|screenSize"
à chaque Activity
de votre fichier AndroidManifest.xml:
<activity
Android:name=".login.LoginActivity"
Android:configChanges="orientation|screenSize">
</activity>
C'est un peu tard mais voici une solution XML-Only, mais une solution de piratage qui ne recrée pas une activité comme le fait setRequestedOrientation
si doit changer d'orientation:
D'autres solutions n'ont pas fonctionné pour moi. Il me restait encore un problème d’orientation étrange avec les problèmes de dialogues et de loisirs. Ma solution a été d'étendre l'activité en la forçant comme portrait dans le manifeste.
Exemple:
public class MainActivityPhone extends MainActivity {}
manifest.xml:
<activity
Android:screenOrientation="portrait"
Android:name=".MainActivityPhone"
Android:theme="@style/AppTheme.NoActionBar" />
dans l'activité splashcreen:
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);
Vieille question que je connais. Pour que votre application fonctionne toujours en mode portrait même lorsque l'orientation peut être ou est intervertie, etc. (par exemple sur des tablettes), j'ai conçu cette fonction qui permet de définir le périphérique dans la bonne orientation sans avoir besoin de savoir les fonctionnalités sont organisées sur l'appareil.
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); }
}
Fonctionne comme un charme!
AVIS: Modifiez this.activity
par votre activité ou ajoutez-le à l'activité principale et supprimez this.activity
;-)
Si vous voulez faire le contraire, vous devez changer le code en paysage (mais je pense qu'il est clair comment procéder).
Malheureusement, l’utilisation de la méthode setRequestedOrientation (...) provoquera le redémarrage de l’activité. Ainsi, même si vous appelez cela dans la méthode onCreate, le cycle de vie de l’activité en sera répété, puis la même activité sera recréée orientation. Donc, dans la réponse de @Brian Christensen, vous devez considérer que le code d'activité peut être appelé deux fois, ce qui peut avoir des effets négatifs (non seulement visuels, mais également lors de requêtes réseau, d'analyses, etc.).
De plus, définir l'attribut configChanges dans le manifeste est, à mon avis, un gros compromis qui pourrait impliquer des coûts de refactorisation énormes. Les développeurs Android ne recommandent pas de modifier cet attribut .
Enfin, essayer de définir screenOrientation d'une manière ou d'une autre (pour éviter le problème de redémarrage) est impossible, statiquement impossible en raison du manifeste statique qui ne peut pas être modifié. Par programme, il est uniquement possible d'appeler cette méthode dans l'activité déjà démarrée.
Résumé: À mon avis, la suggestion de @Brian Christensen est le meilleur compromis, mais soyez conscient du problème de la reprise d'activité.