2012-01-11 52 views
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具體事實是irreleveant。所有應該理解的是它的一個屬性,只有從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屬性值的值。

我正在尋找任何其他方式來從主題中讀取像這樣的屬性。我很確定,一旦我獲得了風格參考,我就不會在閱讀它的屬性時遇到麻煩。

有沒有任何可能的方法來做到這一點?

回答

15

「使用全息同時支持安卓2.x的」我的假設下進行操作,當Android的風格所編制的屬性常數用途是什麼鍵,因此理論上應該是能無論如何都可以在任何平臺上閱讀。

可能,雖然這不是我如何解釋導致您看到的錯誤的C++源代碼。請查看frameworks/base/libs/utils/ResourceTypes.cpp中的ResTable::Theme::applyStyle()

我的解釋是,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++天在我的後視鏡是嚴重,所以我可能誤解了我所看到的。

+0

感謝您深入挖掘。 – 2012-01-15 06:20:07

+0

小小的OT,你怎麼知道/認爲尋找ResourceTypes.cpp?我看到很多由@CommonsWare回答的問題,所以我傾向於認爲你是Android專家。 – 2012-04-29 22:47:08

+1

@ radioact1ve:我可能搜索了錯誤消息文本。 – CommonsWare 2012-04-29 23:08:50

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設備/模擬器上,我都會正確讀入主題,然後進入小部件樣式,以獲得我設置的縮放填充尺寸。

希望我沒有錯過一件大事。

+1

這看起來很有希望,除非我沒有觀察到與您相同的結果。該錯誤仍然在logcat中擡頭。 https://github.com/JakeWharton/PreHCABAttrs – 2012-01-11 23:27:50

+0

我才意識到,所有我測試這對設備2.3(認爲一個是2.2,但它顯然有一個更新)。我在2.1/2.2上看到了同樣的錯誤,所以看起來他們解除了2.3中的限制。你的例子在2.3上工作(好吧,它崩潰了,但是這是因爲navigationMode不作爲int返回,如果它沒有定義...它返回作爲參考ID)。對困惑感到抱歉。 – Devunwired 2012-01-12 04:57:26