web-dev-qa-db-fra.com

Comment puis-je détecter la disposition sélectionnée par Android dans mon application?

Supposons que j'ai une activité avec trois dispositions différentes dans différents dossiers de ressources. Par exemple:

layout-land/my_act.xml
layout-xlarge/my_act.xml
layout-xlarge-land/my_act.xml

Dans différents appareils et différentes positions, l'un d'eux est sélectionné par Android.
Comment puis-je savoir lequel est sélectionné par programme?

Android possède-t-il une API qui renvoie ces dispositions au programme?


Edit : la solution de Graham Borland a un problème dans certaines situations que j'ai mentionnées dans les commentaires.

68
Bobs

Vous pouvez créer un values-<config> répertoire pour chacune de vos configurations prises en charge. À l'intérieur de chacun de ces répertoires, créez un strings.xml avec un seul selected_configuration chaîne qui décrit la configuration actuelle. Au moment de l'exécution, récupérez la chaîne à l'aide de la méthode standard getString, qui effectuera la résolution de configuration pour vous et renverra la chaîne appropriée pour la configuration. Ceci n'est pas testé.

42
Edward Dale

Vous pouvez définir un attribut Android:tag différent sur les vues de chaque fichier de ressources différent et relire la balise au moment de l'exécution avec View.getTag() .

Exemple:

layout-xlarge-land/my_act.xml

<View
    Android:id="@+id/mainview"
    Android:tag="xlarge-landscape"
/>

layout-xlarge/my_act.xml

<View
    Android:id="@+id/mainview"
    Android:tag="xlarge-portrait"
/>

MyActivity.Java

String tag = view.getTag();
if (tag.equals("xlarge-landscape") {
    ...
}
71
Graham Borland

Vous pouvez essayer de répéter cet algorithme "Comment Android trouve la ressource la mieux adaptée" - c'est assez simple, surtout si vous avez des dispositions différentes uniquement pour différents écrans.

8
Jin35

Ma réponse est mise en œuvre à partir de @Graham Borland

 @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        switch(metrics.densityDpi){
             case DisplayMetrics.DENSITY_LOW:

             if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
             {
               Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
               String tag = view.getTag();
               if (tag.equals("small-landscape") {
                .....
              }
             } 
            else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) 
            {
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
             String tag = view.getTag();
               if (tag.equals("small-potrait") {
                .....
              }
            }
            break;

             case DisplayMetrics.DENSITY_MEDIUM:

             if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
             {
               Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
               String tag = view.getTag();
               if (tag.equals("medium-landscape") {
                .....
              }
             } 
            else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) 
            {
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
             String tag = view.getTag();
               if (tag.equals("medium-potrait") {
                .....
              }
            }
             break;

             case DisplayMetrics.DENSITY_HIGH:

               if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
             {
               Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
               String tag = view.getTag();
               if (tag.equals("large-landscape") {
                .....
              }
             } 
            else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) 
            {
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
             String tag = view.getTag();
               if (tag.equals("large-potrait") {
                .....
              }
            }
             break;
        }

Cela fonctionnera au niveau 4 ou supérieur de l'API.

5
Dinesh

Je suppose que vous utilisez setContentView(int resID) pour définir le contenu de vos activités.


MÉTHODE 1 (Voici ma réponse)

Maintenant, dans toutes vos présentations, assurez-vous que la vue racine a toujours la bonne balise:

exemple:

layout-xlarge/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:tag="xlarge-landscape"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <TextView
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/hello" />

</LinearLayout>

layout-small/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:tag="small"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <TextView
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/hello" />

</LinearLayout>

Maintenant, laissez vos activités prolonger cette activité:

package shush.Android.screendetection;

import Android.app.Activity;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class SkeletonActivity extends Activity {

    protected String resourceType;

    @Override
    public void setContentView(int layoutResID) {
        LayoutInflater inflater = getLayoutInflater();
        View view = inflater.inflate(layoutResID, null);
        resourceType = (String)view.getTag();
        super.setContentView(view);
    }
}

Dans ce cas, vous pouvez utiliser le resourceType pour savoir quel est l'identifiant de ressource utilisé.


MÉTHODE 2 (C'était ma réponse mais avant de poster je pensais à la meilleure)

Maintenant, dans toutes vos présentations, assurez-vous que la vue racine a toujours la bonne balise:

exemple:

layout-xlarge/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:tag="xlarge-landscape"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <TextView
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/hello" />

</LinearLayout>

layout-small/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:tag="small"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <TextView
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/hello" />

</LinearLayout>

Maintenant, laissez vos activités prolonger cette activité:

package shush.Android.screendetection;

import Android.app.Activity;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class SkeletonActivity extends Activity {

    @Override
    public void setContentView(int layoutResID) {
        LayoutInflater inflater = getLayoutInflater();
        View view = inflater.inflate(layoutResID, null);
        fix(view, view.getTag());
        super.setContentView(view);
    }

    private void fix(View child, Object tag) {
        if (child == null)
            return;

        if (child instanceof ViewGroup) {
            fix((ViewGroup) child, tag);
        }
        else if (child != null) {
            child.setTag(tag);
        }
    }

    private void fix(ViewGroup parent, Object tag) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            View child = parent.getChildAt(i);
            if (child instanceof ViewGroup) {
                fix((ViewGroup) child, tag);
            } else {
                fix(child, tag);
            }
        }
    }
}

Dans ce cas, toutes vos vues dans votre hiérarchie auront la même balise.

3
Sherif elKhatib

Je ne sais pas exactement comment le trouver. Mais nous pouvons le trouver de manière différente.

Ajoutez une vue de texte dans toutes les mises en page (visibilité masquée). Attribuez des valeurs telles que xlarge, land, xlarge-land en conséquence.

Dans le programme, obtenez la valeur de textview. D'une certaine manière, nous pouvons apprendre comme ça.

2
Raghu Nagaraju

Vous pouvez obtenir des informations sur l'orientation et la taille de l'écran à partir de l'objet Resources. De là, vous pouvez comprendre quelle disposition est utilisée.

getResources().getConfiguration().orientation; - renvoie soit Configuration.ORIENTATION_PORTRAIT soit Configuration.ORIENTATION_LANDSCAPE.

int size = getResources().getConfiguration().screenLayout; - retourne le masque de la taille de l'écran. Vous pouvez tester des tailles petites, normales, grandes et x grandes. Par exemple:

if ((size & Configuration.SCREENLAYOUT_SIZE_XLARGE)==Configuration.SCREENLAYOUT_SIZE_XLARGE)
2
sshturma

Votre question est la même que celle-ci Comment obtenir le chemin du fichier xml de mise en page?
Vous pouvez ajouter une vue de texte masqué avec les noms de dossier correspondants dans le xml Récupérer la chaîne dans la vue de texte en

TextView path = (TextView)findViewbyid(R.id.hiddentextview); 
 String s =  path.gettext().tostring();

Assurez-vous que tous les identifiants de la vue texte sont identiques.

Exemple

if your xml is in `normal-mdpi` in hidden textview hard code `normal-mdpi`
if your xml is in `large-mdpi` in hidden textview hard code `large-mdpi`
1
VenomVendor