How to retrieve style attributes programmatically from styles.xml How to retrieve style attributes programmatically from styles.xml android android

How to retrieve style attributes programmatically from styles.xml


It is possible to retrieve custom styles from styles.xml programmatically.

Define some arbitrary style in styles.xml:

<style name="MyCustomStyle">    <item name="android:textColor">#efefef</item>    <item name="android:background">#ffffff</item>    <item name="android:text">This is my text</item></style>

Now, retrieve the styles like this

// The attributes you want retrievedint[] attrs = {android.R.attr.textColor, android.R.attr.background, android.R.attr.text};// Parse MyCustomStyle, using Context.obtainStyledAttributes()TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, attrs);// Fetch the text from your style like this.     String text = ta.getString(2);// Fetching the colors defined in your styleint textColor = ta.getColor(0, Color.BLACK);int backgroundColor = ta.getColor(1, Color.BLACK);// Do some logging to see if we have retrieved correct valuesLog.i("Retrieved text:", text);Log.i("Retrieved textColor as hex:", Integer.toHexString(textColor));Log.i("Retrieved background as hex:", Integer.toHexString(backgroundColor));// OH, and don't forget to recycle the TypedArrayta.recycle()


The answer @Ole has given seems to break when using certain attributes, such as shadowColor, shadowDx, shadowDy, shadowRadius (these are only a few I found, there might be more)

I have no idea as to why this issue occurs, which I am asking about here, but @AntoineMarques coding style seems to solve the issue.

To make this work with any attribute it would be something like this


First, define a stylable to contain the resource ids like so

attrs.xml

<resources>         <declare-styleable name="MyStyle" >        <attr name="android:textColor" />        <attr name="android:background" />        <attr name="android:text" />    </declare-styleable></resources>

Then in code you would do this to get the text.

TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, R.styleable.MyStyle);  String text = ta.getString(R.styleable.MyStyle_android_text);

The advantage of using this method is, you are retrieving the value by name and not an index.


The answers from Ole and PrivatMamtora didn't work well for me, but this did.

Let's say I wanted to read this style programmatically:

<style name="Footnote">    <item name="android:fontFamily">@font/some_font</item>    <item name="android:textSize">14sp</item>    <item name="android:textColor">@color/black</item></style>

I could do it like this:

fun getTextColorSizeAndFontFromStyle(    context: Context,     textAppearanceResource: Int // Can be any style in styles.xml like R.style.Footnote) {    val typedArray = context.obtainStyledAttributes(        textAppearanceResource,        R.styleable.TextAppearance // These are added to your project automatically.    )    val textColor = typedArray.getColorStateList(        R.styleable.TextAppearance_android_textColor    )    val textSize = typedArray.getDimensionPixelSize(        R.styleable.TextAppearance_android_textSize    )    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {        val typeface = typedArray.getFont(R.styleable.TextAppearance_android_fontFamily)        // Do something with the typeface...    } else {        val fontFamily = typedArray.getString(R.styleable.TextAppearance_fontFamily)            ?: when (typedArray.getInt(R.styleable.TextAppearance_android_typeface, 0)) {                1 -> "sans"                2 -> "serif"                3 -> "monospace"                else -> null            }        // Do something with the fontFamily...    }    typedArray.recycle()}

I took some inspiration from Android's TextAppearanceSpan class, you can find it here: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/TextAppearanceSpan.java