开发者

Android - reference the value of an attribute in the currently-applied theme from code

the Android devGuide explains how it is possible to reference the value of an attribute in开发者_如何学编程 the currently-applied theme, using the question-mark (?) instead of at (@).

Does anyone know how to do this from code, e.g. in a customized component?


In XML, it would look something like this:

style="?header_background"

programmatically, it's a little trickier. In your activity:

private static Theme theme = null;

protected void onCreate(Bundle savedInstanceState) {
   ...
   theme = getTheme();
   ...
}

public static int getThemeColors(int attr){
   TypedValue typedvalueattr = new TypedValue();
   theme.resolveAttribute(attr, typedvalueattr, true);
   return typedvalueattr.resourceId;
}

And when you want to access an attribute of the theme, you would do something like this:

int outside_background = MyActivity.getThemeColors(R.attr.outside_background);
setBackgroundColor(getResources().getColor(outside_background));

It's a little more convoluted, but there you go ;-)


The above is not a good way of doing this for many reasons. NullPointerExceptions is one.

Below is the correct way of doing this.

public final class ThemeUtils {
    // Prevent instantiation since this is a utility class
    private ThemeUtils() {}

   /**
    * Returns the color value of the style attribute queried.
    *
    * <p>The attribute will be queried from the theme returned from {@link Context#getTheme()}.</p>
    *
    * @param context the caller's context
    * @param attribResId the attribute id (i.e. R.attr.some_attribute)
    * @param defaultValue the value to return if the attribute does not exist
    * @return the color value for the attribute or defaultValue
    */
    public static int getStyleAttribColorValue(final Context context, final int attribResId, final int defaultValue) {
        final TypedValue tv = new TypedValue();
        final boolean found = context.getTheme().resolveAttribute(attribResId, tv, true);
        return found ? tv.data : defaultValue;
    }
}

Then to use just do:

final int attribColor = ThemeUtils.getStyleAttribColorValue(context, R.attr.some_attr, 0x000000 /* default color */);

Just make sure the context that you pass in came from the Activity. Don't do getApplicationContext() or the theme returned will be from the Application object and not the Activity.


After several hours I finally found a working solution, the ones above returned only the ressourceId, not the color. You can use this instead:

public static int getThemeColor(Context context, int attr) {
    TypedValue typedValue = new TypedValue();
    context.getTheme().resolveAttribute(attr, typedValue, true);
    TypedArray ta = context.obtainStyledAttributes(typedValue.resourceId, new int[]{attr});
    int color = ta.getColor(0, 0);
    ta.recycle();
    return color;
}

Change ta.getColor(0, 0) with what you want to get, you can replace it with ta.getDimensionPixelSize(0, 0) for example. If you want to set a fallback value, replace the second 0 with whatever value you need.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜