30

アプリケーションを実行しているプラ​​ットフォームよりも新しいプラットフォーム用に設計されたテーマとスタイルから属性値を読み取ろうとしています。

理由を聞かないでください。私が書いたライブラリについて何か知っているなら、私がプラットフォームの機能をプッシュしたいことをすでに知っているはずです:)

私は、Android スタイルがコンパイルされるときに属性定数がキーに使用されるものであるため、理論的にはどのプラットフォームでも何らかの方法で読み取ることができるはずであるという前提で操作しています。これは、他のライブラリのレイアウト XML で問題なく発生していることを確認したものです。

問題を示すベース テスト ケースを次に示します。これは、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>

これがandroid:actionBarStyle特に使用するという事実は無関係です。理解する必要があるのは、Android 3.0 以降でのみ使用できる属性であるということだけです。

Android 3.0 より前のプラットフォームでこれまでにこれらの値にアクセスしようとした方法を次に示します。

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

<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"
    />

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

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);

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

それらはすべて、LogCat で次のエラーになります。

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

0x010102ce定数は、その値にアクセスする機会を得る前に、プラットフォームが属性を拒否していることを示しているように見える属性値ですandroid.R.attr.actionBarStyle

このような属性をテーマから読み取る他の方法を探しています。スタイル リファレンスを取得すれば、その属性の読み取りに問題はないと確信しています。

これを行う方法はありますか?

4

3 に答える 3

15

私は、Android スタイルがコンパイルされるときに属性定数がキーに使用されるものであるため、理論的にはどのプラットフォームでも何らかの方法で読み取ることができるはずであるという前提で操作しています。

おそらく、それはあなたが見ているエラーを発生させるC++ソースコードを解釈する方法ではありません. でチェックアウトResTable::Theme::applyStyle()frameworks/base/libs/utils/ResourceTypes.cppます。

私の解釈では、Android には、パッケージのメモリ内テーブルに相当するものがあります->タイプ->可能なエントリ:

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

あなたのエントリ インデックスは、既知の最高のエントリよりも高くなっています:

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

android他のパッケージとは異なるこれを処理する可能性があります-androidファームウェアのビルド時に既知の値を使用します(新しいプラットフォームからのものであるため、生成されたエントリインデックスは高くなります)、非androidものは何でも有効であると想定します。

私の推測が正しければ、あなたがやりたいことはうまくいきません。そうは言っても、私の C++ 時代は真剣にバックミラーに映っているので、見ているものを誤解している可能性があります。

于 2012-01-11T12:27:54.690 に答える
4

おそらく私はここで最終目標を見逃していますが、2.x デバイスで問題なくすべての属性を読み取ることができた次の例をまとめました。この例は、3.0 targetSdk に対してコンパイルされました。

styles.xml (スタイルとテーマを宣言します)

<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 (実行時に取得する属性グループを宣言します)

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

AndroidManifest.xml (カスタム テーマを適用)

<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 (属性を掘り下げる)

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);
}

例を 3.0 に対してコンパイルする限り、すべての属性名を解決できます。私が持っているすべての2.Xデバイス/エミュレーターで、これはテーマに正しく読み込まれ、次にウィジェットスタイルに読み込まれ、設定したスケーリングされたパディングディメンションが取得されます。

何か大きなものを見逃さなかったことを願っています。

于 2012-01-11T20:11:58.307 に答える
-1

おそらく、いくつかのテーマを定義する必要があります。古いデバイスの場合は、フォルダー res/values-v11/themes.xml を使用します。http://android-developers.blogspot.com/2012/01/holo-everywhere.htmlのセクション「Android 2.x をサポートしながら Holo を使用する」を参照してください。

于 2012-01-11T09:09:24.963 に答える