2

I've implemented a custom view with custom attributes and I am trying to style it in the theme. I've followed the instructions in this answer, but my widget is not picking up the style from the app theme.

The custom attributes for my widget:

<declare-styleable name="BarGraph">
    <attr name="barColour" format="color"/>
    <attr name="barWidth" format="dimension"/>
    <attr name="maxBarHeight" format="dimension"/>
    <attr name="barWhiteSpace" format="dimension"/>
</declare-styleable>

Declare the style reference:

<declare-styleable name="CustomTheme">
    <attr name="barGraphStyle" format="reference"/>
</declare-styleable>

Style my widget:

<style name="AppTheme.BarGraphStyle" parent="AppTheme">
    <item name="barColour">?attr/colorAccent</item>
    <item name="barWidth">@dimen/bar_graph_bar_width</item>
    <item name="maxBarHeight">@dimen/bar_graph_bar_max_height</item>
    <item name="barWhiteSpace">@dimen/bar_white_space</item>
</style>

Add the style to my app's theme:

<style name="AppTheme" parent="Theme.AppCompat.Light">
    ...
    <item name="barGraphStyle">@style/AppTheme.BarGraphStyle</item>
</style>

Finally, I get the custom attributes in my custom component's constructor:

TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.BarGraph);
ColorStateList barColour = styledAttributes.getColorStateList(R.styleable.BarGraph_barColour);
Log.d(TAG, "BarGraph: barColour = " + barColour);

float barWidth = styledAttributes.getDimension(R.styleable.BarGraph_barWidth, -1);
float maxHeight = styledAttributes.getDimension(R.styleable.BarGraph_maxBarHeight, -1);
float barWhiteSpace = styledAttributes
            .getDimension(R.styleable.BarGraph_barWhiteSpace, -1);
    styledAttributes.recycle();
Log.d(TAG, "BarGraph: barWidth = " + barWidth);
Log.d(TAG, "BarGraph: maxHeight = " + maxHeight);
Log.d(TAG, "BarGraph: barWhiteSpace = " + barWhiteSpace);

Log output from the constructor:

D/BarGraph( 6862): BarGraph: barColour = null
D/BarGraph( 6862): BarGraph: barWidth = -1.0
D/BarGraph( 6862): BarGraph: maxHeight = -1.0 
D/BarGraph( 6862): BarGraph: barWhiteSpace = -1.0

If I apply the style directly on my widget, using style="@style/AppTheme.BarGraphStyle", it styles correctly, so I know it's not a problem with the style itself.

Edit: my constructors:

public BarGraph(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
}

public BarGraph(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    // grab all the custom styling values
    TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.BarGraph);
    ColorStateList barColour = styledAttributes.getColorStateList(R.styleable.BarGraph_barColour);
    Log.d(TAG, "BarGraph: barColour = " + barColour);

    float barWidth = styledAttributes.getDimension(R.styleable.BarGraph_barWidth, -1);
    float maxHeight = styledAttributes.getDimension(R.styleable.BarGraph_maxBarHeight, -1);
    float barWhiteSpace = styledAttributes .getDimension(R.styleable.BarGraph_barWhiteSpace, -1);
    styledAttributes.recycle();

    Log.d(TAG, "BarGraph: barWidth = " + barWidth);
    Log.d(TAG, "BarGraph: maxHeight = " + maxHeight);
    Log.d(TAG, "BarGraph: barWhiteSpace = " + barWhiteSpace);

    // other non-styling code...
}
3
  • Can u plz post all constructors of your custom component? Commented Sep 13, 2016 at 13:51
  • @AndreClassen added them Commented Sep 13, 2016 at 13:56
  • 1
    AppTheme.BarGraphStyle is not supposed to inherit from a whole theme. "" or "android:Widget" would be great parents. While at it change the name to better reflect that it's a style and not a theme. Widget.BarGraph would be nice. Commented Sep 26, 2016 at 20:44

2 Answers 2

2

Change your second constructor like this,

public BarGraph(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.barGraphStyle);
    }

And inside your third constructor, use this line

    TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.BarGraph, defStyleAttr, R.style.AppTheme_BarGraphStyle);

You have missed these lines. It's working perfectly for me with this code.

Sign up to request clarification or add additional context in comments.

1 Comment

BarGraph(Context, AttributeSet) is the contructor invoked while inflating from XML. R.attr.barGraphStyle is the (optional) theme attribute pointing to a style. R.style.AppTheme_BarGraphStyle is a style containing default values. Values from this default style will always be picked unless they're overridden by the barGraphsStyle theme attribute or style attribute or direct attributes.
1
+50

Constructors should be like this:

    public BarGraph(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.barGraphStyle);
    }

    public BarGraph(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyle) {
        super(context, attrs, defStyle);

        // grab all the custom styling values
        TypedArray styledAttributes = context.obtainStyledAttributes( attrs, R.styleable.BarGraph, defStyle, 0);

        ...
    }

2 Comments

Won't that just use the default, though?
@AesSedai101 What are you worry about? R.attr.barGraphStyle refers the style defined in AppTheme. There is problems?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.