Skip to content

Instantly share code, notes, and snippets.

@evelyne24
Last active May 8, 2021 15:40
Show Gist options
  • Save evelyne24/6736456 to your computer and use it in GitHub Desktop.
Save evelyne24/6736456 to your computer and use it in GitHub Desktop.
This is how to get the colour from a custom style within a custom style within an Android Theme.
package org.codeandmagic.android.customtheme;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.TextView;
/**
* Created by evelyne24.
*/
public class CustomTextView extends TextView {
public static final String T = "=THEME=";
public CustomTextView(Context context) {
super(context);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
final TypedValue result = resolveThemeStyle(context.getTheme(), new int[]{R.attr.myDialogStyle,
R.attr.myDialogTitleStyle, android.R.attr.background}, 0, 2);
if (TypedValue.TYPE_INT_COLOR_RGB8 == result.type) {
String strColor = String.format("#%06X", 0xFFFFFF & result.data);
setBackgroundColor(Color.parseColor(strColor));
}
}
private TypedValue resolveThemeStyle(Resources.Theme theme, int[] attrs, int level, int maxLevel) {
TypedValue typedValue = new TypedValue();
theme.resolveAttribute(attrs[level], typedValue, true);
if (typedValue.type == TypedValue.TYPE_REFERENCE) {
Log.i(T, "level " + level + ": found reference " + typedValue.resourceId);
Resources.Theme newTheme = getResources().newTheme();
newTheme.applyStyle(typedValue.resourceId, true);
if (level == maxLevel) {
return typedValue;
} else {
return resolveThemeStyle(newTheme, attrs, level + 1, maxLevel);
}
} else {
return typedValue;
}
}
}
@evelyne24
Copy link
Author

This is in style.xml

<resources>
    <style name="AppTheme" parent="android:Theme">
        <item name="myDialogStyle">@style/LightDialogStyle</item>
    </style>
    <style name="LightDialogStyle">
        <item name="myDialogTitleStyle">@style/LightDialogTitleStyle</item>
    </style>
    <style name="LightDialogTitleStyle" parent="android:Widget.TextView">
        <item name="android:background">#ff0000</item>
    </style>
</resources>

@evelyne24
Copy link
Author

This is in attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myDialogTitleStyle" format="reference" />
    <attr name="myDialogStyle" format="reference" />
</resources>

@evelyne24
Copy link
Author

This is in main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <org.codeandmagic.android.customtheme.CustomTextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        style="?myDialogTitleStyle"/>

</RelativeLayout>

@evelyne24
Copy link
Author

My problem is: even if I put style="?myDialogTitleStyle", Android won't recursively find that particular style in my theme so I have to recurse and get the attribute values myself. What am I doing wrong? Is this the intended behaviour?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment