28 votes

Lire les attributs de thème plus récents sur une plateforme plus ancienne

Je suis en train de lire les valeurs d'attribut à partir de thèmes et de styles qui ont été conçus pour les plates-formes qui sont plus récents que je suis en cours d'exécution de mon application.

S'il vous plaît ne me demandez pas pourquoi. Si vous savez quelque chose sur les bibliothèques j'écris, alors vous devriez déjà savoir que j'aime tester les capacités de la plate-forme :)

Je suis d'exploitation en vertu de la présomption que quand Android styles sont compilées à l'attribut constantes sont ce qui est utilisé pour les touches et, par conséquent, en théorie, doit pouvoir être lu sur n'importe quel plate-forme en quelque sorte. C'est ce que j'ai observé à se produire avec mise en page XMLs dans mes autres bibliothèques sans trop de mal.

Voici une base de cas de test qui montre le problème. Ce doit être compilé à l'aide de Android 3.0+.

<resources>
    <style name="Theme.BreakMe">
        <item name="android:actionBarStyle">@style/Widget.BreakMe</item>
    </style>
    <style name="Widget.BreakMe" parent="android:Widget">
        <item name="android:padding">20dp</item>
    </style>
</resources>

Le fait qu'il utilise android:actionBarStyle plus précisément, c'est irreleveant. Tout ce qui doit être compris, c'est que c'est un attribut qui était uniquement disponible à partir d'Android 3.0.

Voici le chemin que j'ai essayé d'accéder à ces valeurs jusqu'à présent sur les plates-formes avant d'Android 3.0.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Break Me"
    style="?android:attr/actionBarStyle"
    />

et

<declare-styleable name="Whatever">
    <item name="datStyle" format="reference" />
</declare-styleable>

<style name="Theme.BreakMe.Take2">
    <item name="datStyle">?android:attr/actionBarSize</item>
</style>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Break Me"
    style="?attr/datStyle"
    />

et

TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarStyle, outValue, true);

et

int[] Theme = new int[] { android.R.attr.actionBarSize };
int Theme_actionBarSize = 0;
TypedArray a = context.obtainStyledAttributes(attrs, Theme);
int ref = a.getResourceId(Theme_actionBarSize, 0);

et

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, android.R.attr.actionBarStyle, 0);

Tous d'entre eux à l'origine de cette erreur dans le LogCat:

E/ResourceType(5618): Style contains key with bad entry: 0x010102ce

L' 0x010102ce constante, c'est la valeur de l'attribut d' android.R.attr.actionBarStyle ce qui semble indiquer la plate-forme est le rejet de l'attribut avant que je puisse même avoir une chance d'accéder à sa valeur.

Je suis à la recherche de toute autre manière de lire les attributs comme ce Thème. Je suis assez sûr qu'une fois que j'ai obtenu le style de référence, je ne vais pas avoir des problèmes de lecture de ses attributs.

Est-il possible de faire cela?

14voto

CommonsWare Points 402670

Je suis d'exploitation en vertu de la présomption que quand Android styles sont compilées à l'attribut constantes sont ce qui est utilisé pour les touches et, par conséquent, en théorie, doit pouvoir être lu sur n'importe quel plate-forme en quelque sorte.

Éventuellement, si ce n'est pas comment je suis interprète le C++ source code qui génère l'erreur que vous voyez. Découvrez ResTable::Theme::applyStyle() en frameworks/base/libs/utils/ResourceTypes.cpp.

Mon interprétation est que Android est ce qui revient à une table en mémoire de paquets->type->entrées possibles:

numEntries = curPI->types[t].numEntries;

Votre entrée d'index est plus élevé que le plus connu d'entrée:

if (e >= numEntries) {
    LOGE("Style contains key with bad entry: 0x%08x\n", attrRes);
    bag++;
    continue;
}

Il est possible qu'ils manipulent ce différent pour android par rapport aux autres paquets -- android utilise des valeurs connues au firmware moment de la construction (et votre générés entrée d'index est supérieur, car c'est à partir d'une plate-forme plus récente), non-android ceux de supposer quoi que ce soit de valable.

Si ma conjecture est correcte, ce que vous voulez faire ne fonctionnera pas. Cela étant dit, mon C++ jours sont sérieusement dans mon rétroviseur, donc j'ai peut-être mal interprété ce que je vois.

4voto

Devunwired Points 27023

Peut-être que je vais manquer l'objectif de la fin ici, mais j'ai mis en place l'exemple suivant, qui a été en mesure de lire tous les attributs sans problème sur n'importe quel 2.x l'appareil. L'exemple a été compilé avec un 3.0 targetSdk.

styles.xml (Déclarer les styles et thèmes)

<resources>
  <style name="Theme.NewFeatures" parent="android:Theme">
      <item name="android:actionBarStyle">@style/Widget.MyActionBar</item>
  </style>
  <style name="Widget.MyActionBar" parent="android:Widget">
      <item name="android:padding">20dp</item>
  </style>
</resources>

attrs.xml (Déclarer les groupes d'attributs que vous souhaitez obtenir à l'exécution)

<resources>
  <declare-styleable name="ActionBarNewFeatures">
    <attr name="android:actionBarStyle" />
  </declare-styleable>
  <declare-styleable name="MyWidgetNewFeatures">
      <attr name="android:padding" />
  </declare-styleable>
</resources>

AndroidManifest.xml (Appliquer le thème personnalisé)

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.NewFeatures" >
    <activity
        android:name=".SomeActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

SomeActivity.java (Aller creuser pour les attributs)

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    TypedArray a = obtainStyledAttributes(R.styleable.ActionBarNewFeatures);
    //Get the style ID for the widget
    int resid = a.getResourceId(R.styleable.ActionBarNewFeatures_android_actionBarStyle, -1);
    a.recycle();

    a = obtainStyledAttributes(resid, R.styleable.MyWidgetNewFeatures);
    int padding = a.getDimensionPixelSize(R.styleable.MyWidgetNewFeatures_android_padding, -1);
    a.recycle();

    TextView tv = new TextView(this);
    tv.setText(String.format("Padding will be %d px", padding));
    setContentView(tv);
}

Aussi longtemps que je le compiler l'exemple contre 3.0 de sorte qu'il peut résoudre tous les noms d'attribut; sur tous les 2.X appareil/émulateur, j'ai ceci permettra de lire correctement dans le thème, puis dans le style de widget pour obtenir de l'échelle rembourrage dimension que j'avais fixé.

Espère que je n'ai pas manqué quelque chose de grand.

-1voto

serj Points 153

Probablement, vous devez définir quelques thèmes. Pour les anciens appareils, utilisez le dossier res / values-v11 / themes.xml. Voir la section "Utiliser Holo tout en prenant en charge Android 2.x" dans le http://android-developers.blogspot.com/2012/01/holo-everywhere.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X