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...
}
Community
  • 1
  • 1
AesSedai101
  • 1,502
  • 2
  • 23
  • 37

2 Answers2

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.

Bob
  • 13,447
  • 7
  • 35
  • 45
  • `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. – Eugen Pechanec Sep 26 '16 at 20:48
1

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

        ...
    }
nshmura
  • 5,940
  • 3
  • 27
  • 46