Read Newer Theme Attributes On Older Platform

陌路散爱 提交于 2019-12-02 17:30:34

I am operating under the presumption that when Android styles are compiled the attribute constants are what is used for the keys and therefore should theoretically be able to be read on any platform somehow.

Possibly, though that is not how I am interpreting the C++ source code that raises the error you are seeing. Check out ResTable::Theme::applyStyle() in frameworks/base/libs/utils/ResourceTypes.cpp.

My interpretation is that Android has what amounts to an in-memory table of packages->types->possible entries:

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

Your entry index is higher than the highest known entry:

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

It is possible that they handle this different for android versus other packages -- android uses known values at firmware build time (and your generated entry index is higher, because it is from a newer platform), non-android ones assume anything's valid.

If my guesswork is correct, what you want to do will not work. That being said, my C++ days are seriously in my rear-view mirror, so I may be misinterpreting what I'm seeing.

Perhaps I'm missing the end goal here, but I put together the following example that was able to read out all the attributes without issue on any 2.x device. The example was compiled against a 3.0 targetSdk.

styles.xml (Declare the styles and themes)

<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 (Declare the attribute groups you wish to obtain at runtime)

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

AndroidManifest.xml (Apply the custom theme)

<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 (Go digging for attributes)

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

As long as I compile the example against 3.0 so it can resolved all the attribute names; on every 2.X device/emulator I have this will correctly read into the theme and then into the widget style to get the scaled padding dimension I had set.

Hope I didn't miss something big.

Probably, You must define a few themes. For old devices use folder res/values-v11/themes.xml. See section "Using Holo while supporting Android 2.x" in the http://android-developers.blogspot.com/2012/01/holo-everywhere.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!