Android: autoriser le portrait et le paysage pour les tablettes, mais forcer le portrait sur le téléphone?
Je voudrais que les tablettes puissent s'afficher en portrait et en paysage (sw600dp ou supérieur), mais que les téléphones soient limités au portrait seulement. Je ne trouve aucun moyen de choisir conditionnellement une orientation. Toutes les suggestions?
8 réponses
Voici une bonne façon à l'aide de ressources et taille qualificatifs.
Mettez cette ressource bool dans res / values en tant que bools.xml ou autre (les noms de fichiers n'ont pas d'importance 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 pour ajouter ces répertoires et fichiers dans Android Studio.
Ensuite, dans la méthode onCreate de vos activités, vous pouvez faire ceci:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Périphériques qui sont plus de 600 dp dans la plus petite direction de largeur, ou X-large sur les appareils pré-Android 3.2 (tablettes, fondamentalement) se comportera comme normal, basé sur le capteur et la rotation verrouillée par l'utilisateur, etc . Tout le reste (téléphones, à peu près) sera portrait seulement.
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éfinissez l'orientation en fonction de cela
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 voulez pouvoir changer entre portrait et paysage (assurez - vous d'ajouter screenSize-vous n'aviez pas besoin de cela!) Vous n'avez pas besoin de définir une orientation d'écran ici. :
android:configChanges="keyboardHidden|orientation|screenSize"
Méthodes à ajouter dans 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'orientation)
@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 est de savoir comment faire pour que l'application change les fichiers de mise en page lors du passage du paysage au portrait ou vice versa. Je suppose que la réponse fait quelque chose de similaire à ce que fait le lien ci - dessus, mais je ne pouvais pas que cela fonctionne pour moi-il a supprimé toutes mes données. Mais si vous avez une application assez simple que vous avez le même fichier de mise en page pour le portrait et le paysage, cela devrait fonctionner.
Supplément à la réponse acceptée
, Vous pouvez effectuer les étapes suivantes dans Android Studio pour ajouter le res/values-sw600dp
et res/values-large
répertoires avec leurs bools.xml
fichiers.
Valeurs-sw600dp
Tout d'abord, dans L'onglet Projet, sélectionnez le filtre projet (plutôt que Android) dans le navigateur.
Puis cliquez avec le bouton droit sur le répertoire app/src/main/res
. Choisir Nouveau > Répertoire De Ressources Android .
Sélectionner plus Petite Largeur de l'Écran, puis appuyez sur la >> bouton.
Saisissez 600
pour la plus petite largeur d'écran. Le nom du répertoire sera généré automatiquement. Dis OK.
Puis faites un clic droit sur le fichier values-sw600dp
nouvellement créé. Choisir Nouveau > valeurs du fichier de ressources . Tapez bools
pour le nom.
Valeurs-grand
L'ajout d'un répertoire values-large
n'est nécessaire que si vous sont en charge pré Android 3.2 (API Niveau 13). Sinon, vous pouvez sauter 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 la plus petite largeur D'écran. Sélectionnez Grand. 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
.
Eh bien, c'est un peu tard Mais, voici un XML uniquement mais une solution de hack qui ne recrée pas une activité comme le fait setRequestedOrientation
si doit changer d'orientation:
Suivant la réponse de Ginny , je pense que la façon la plus fiable de le faire est la suivante:
Comme décrit ici , mettez un booléen dans resources sw600dp. Il doit avoir le préfixe sw sinon il 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>
Ensuite, faites 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 à partir des activités où vous le souhaitez 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 étendez à partir de BaseActivity
, vous devez ajouter la ligne android:configChanges="orientation|screenSize"
pour chaque Activity
dans votre AndroidManifest.xml:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
Vieille question que je connais. Pour exécuter votre application en mode portrait, même lorsque l'orientation peut être ou est échangé etc (par exemple sur les tablettes), j'ai conçu cette fonction est utilisée pour régler l'appareil dans le bon sens sans le besoin de savoir comment le portrait et les caractéristiques du paysage 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 en face, vous devez changer le code en paysage (mais je pense qu'il est clair comment cela).
Malheureusement, en utilisant la méthode setRequestedOrientation(...) provoquera le redémarrage de l'activité, donc même si vous appelez cela dans la méthode onCreate, il passera par le cycle de vie de l'activité et recréera la même activité dans l'orientation demandée. Donc, à la réponse de @Brian Christensen, vous devriez considérer que le code d'activité peut être appelé deux fois, cela pourrait avoir de mauvais effets (non seulement visuels, mais aussi sur les requêtes réseau, les analyses, etc.).
En outre, pour définir l'attribut configChanges dans le manifeste est à mon avis Un gros compromis, ce qui pourrait prendre un coût de refactoring massif. les développeurs Android ne recommandent pas de modifier cet attribut .
Enfin, essayer de définir l'orientation de l'écran différemment (pour éviter le problème de redémarrage)est impossible, statiquement impossible en raison du Manifeste statique qui ne peut pas être modifié, par programmation, il est seulement 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 l'activité de redémarrage.