我正在尝试从主题和样式中读取属性值,这些属性值是为比运行我的应用程序更新的平台而设计的。
请不要问为什么。如果您对我编写的库有所了解,那么您应该已经知道我希望推动该平台的功能:)
我的假设是,在编译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
的属性值,似乎表明平台在我甚至有机会访问其值之前拒绝该属性。
我正在寻找从主题中读取此类属性的任何其他方法。我很确定,一旦我获得了样式参考,我就不会有阅读其属性的麻烦。
有没有办法做到这一点?
答案 0 :(得分:15)
我的假设是,在编译Android样式时,属性常量是用于键的内容,因此理论上应该能够以某种方式在任何平台上读取。
可能,虽然这不是我解释引发你所看到的错误的C ++源代码的方式。查看ResTable::Theme::applyStyle()
中的frameworks/base/libs/utils/ResourceTypes.cpp
。
我的解释是,Android有一个内存的包裹表 - &gt; types-&gt;可能的条目:
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 ++时代在我的后视镜中认真,所以我可能误解了我所看到的。
答案 1 :(得分: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设备/模拟器上我都会正确读入主题,然后进入小部件样式以获得我设置的缩放填充维度。
希望我没有错过任何大事。
答案 2 :(得分:-1)
可能您必须定义一些主题。对于旧设备,请使用文件夹res / values-v11 / themes.xml。请参阅http://android-developers.blogspot.com/2012/01/holo-everywhere.html
中的“在支持Android 2.x时使用Holo”部分