web-dev-qa-db-fra.com

Android incohérences de la disposition et des valeurs de sélection des ressources)

Le problème que je rencontre indique que le compartiment de ressources sélectionné pour le layout XML d'une activité donnée n'est pas cohérent avec les ressources sélectionnées dans le dossier values malgré les mêmes qualificatifs de ressources utilisés dans chaque ensemble de dossiers.

Exemple

Après avoir placé du code de journalisation dans l'activité parent abstraite de mon application, je peux voir que lorsque je démarre mon application sur un émulateur de type Nexus 7 (Android 4.1), la plus petite largeur est en effet de 600dp, le layout-sw600dp-* le dossier est utilisé pour récupérer l'interface utilisateur de l'activité, mais le dossier utilisé pour le values est values-large-*. Je m'attendais à ce que ce soit values-sw600dp-* me fournissant ainsi les informations essentielles sur la catégorie de ressources sous laquelle l'activité est exécutée.

Code effectuant la journalisation au sein de l'activité parent de mon application pour tous Android.app.Activitys

  protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    final Configuration config = getResources().getConfiguration();
    Log.i(this.getClass().getSimpleName(), String.format("Smallest width is [%s]", config.smallestScreenWidthDp));
    configurationContext = SupportedDeviceConfiguration.fromResourceQualifer(getString(string.resourceQualifier));
    Log.i(this.getClass().getSimpleName(), String.format("Running under the [%s] configuration context.", configurationContext.getResourceQualifier()));
...

Journalisation de la sortie lorsque j'exécute ce code sur un appareil de type Nexus 7;

[Logging fluff] Smallest width is [600]
[Logging fluff] Running under the [layout-large-land] configuration context.

Je sais ce que vous pensez - d'où vient cette dérivation layout-large-land ? Continuer à lire...

Contexte

Je teste une approche décrite ici qui me permettrait d'inspecter le compartiment de ressources en cours d'utilisation au moment de l'exécution. L'approche que j'ai mise en œuvre a essentiellement la structure suivante de qualificatifs de ressources;

- res
  + layout                   // Default portrait layout.
  + layout-land              // Default landscape layout
  + layout-large-land        // pre 3.2 phablet landscape layout (Galaxy Note at v2.3.3)
  + layout-xlarge-land       // pre 3.2 tablet landscape layout
  + layout-xlarge-port       // pre 3.2 tablet portrait layout
  + layout-sw520dp-port      // post 3.1 phablet portrait layout (Galaxy Note at v4.0.3)
  + layout-sw520dp-land      // post 3.1 phablet landscape layout
  + layout-sw600dp-port      // post 3.1 mini-tablet portrait layout (Nexus 7)
  + layout-sw600dp-land      // post 3.1 mini-tablet-landscape layout 
  + layout-sw700dp-port      // post 3.1 tablet portrait layout
  + layout-sw700dp-land      // post 3.1 tablet landscape layout
  - values                   // Contains the root strings.xml
     strings.xml
  - values-land
     default-config.xml            
  - values-large-land
     default-config.xml        
  - values-xlarge-land
     default-config.xml     
  - values-xlarge-port
     default-config.xml     
  - values-sw520dp-port
     default-config.xml     
  - values-sw520dp-land
     default-config.xml     
  - values-sw600dp-port
     default-config.xml     
  - values-sw600dp-land
     default-config.xml     
  - values-sw700dp-port
     default-config.xml     
  - values-sw700dp-land
     default-config.xml

Donc, essentiellement, les qualificatifs values reflètent ceux des qualificatifs layout. Sous chacun des values-* dossiers J'ai défini un seul fichier XML appelé device-config.xml avec contenu;

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="resourceQualifier">layout-{qualifier of values folder}</string>
</resources>

Ainsi, par exemple, le values-sw600dp-land Dossiers device-config.xml contient une seule chaîne avec la valeur layout-sw600dp-land. L'objectif ici est que mon code reste synchronisé avec les dispositions de ressources affichées à l'écran. Cela est nécessaire pour que mon code ne se déclenche pas en "trouvant par identifiant" un élément qui n'existe pas sur la présentation affichée en raison de l'immobilier concerné.

(Facultatif) Un raisonnement plus profond pour expliquer pourquoi je fais cela

Le raisonnement plus profond pour vouloir connaître le compartiment utilisé lors de l'exécution est né de la prise de conscience que mon code de configuration à fragment unique pour tous devenait difficile à gérer avec diverses logiques basées sur des commutateurs qui n'étaient pas transparentes et souvent des fonctionnalités dupliquées de d'autres dispositions ... c'était comme si j'avais besoin d'une sorte de Fragment Inheritance ... qui si vous suivez le lien est exactement ce que j'ai fait. L'inconvénient est que je dois savoir avec quel écran je travaille avant de demander au framework d'instancier le fragment x, y ou z, sachant que le fragment en cours de création ne sera jamais désynchronisé avec la mise en page avec laquelle il fonctionne. est censé se gonfler. Cet héritage fonctionne et permet une pile de fragments beaucoup plus gérable (Sonar est aussi plus heureux, ce qui est agréable).

Résumé

Cependant, j'ai été contrarié par cette divergence apparente entre le dossier de présentation et le dossier de valeurs que le cadre sélectionne. Chacun a les mêmes qualificatifs, alors pourquoi une activité ne s'appuyant pas sur le layout-sw600dp-land UI XML utilise le values-sw600dp-land Ressource? J'espère que j'ai quelque chose de mal parce que c'était la plus soignée des solutions potentielles publiées sur la discussion SO que j'ai liée à ci-dessus.

38
OceanLife

Je suis sûr que vous avez affaire à la priorité des ressources utilisée pour la sélection.

Si vous fournissez des dossiers:

layout-sw600dp-*
values-large-*
values-sw600dp-*

Android n'est pas obligé de faire correspondre les valeurs du dossier de sélection à celles de la disposition , il utilise plutôt la même logique de priorité séparément pour la mise en page et séparément pour le dossier de valeurs.

Vous pouvez en savoir plus sur cet algorithme de sélection ici: http://developer.Android.com/guide/topics/resources/providing-resources.html#BestMatch

17
Pointer Null

Je fais une application pour Android 4.0.3. Si vous utilisez le sw600dp, sw720dp, il est nécessaire d'utiliser le suivant?: - values-sw600dp-port default-config.xml
- values-sw600dp-land default-config.xml
- values-sw700dp-port default-config.xml
- values-sw700dp-land default-config.xml car je n'utilise pas res/values-XXX et il semble fonctionner correctement.

1
Adrian