question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[MaterialButton] Creating a button with a style programmatically does not set all attributes

See original GitHub issue

When creating a MaterialButton in code and passing a style from styles.xml not all attributes apply to the button,. Specifically backgroundTint, iconTint, and textColor, although there may be others. When building the component from an xml layout all styling is applied correctly

Expected behavior: Styles should be applied as if they were created in xml

`val button = MaterialButton(newContext, null, R.style.Widget_Cladwell_Button_FilterCapsule)

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowLightStatusBar">true</item> </style> <style name="Widget.Cladwell.Button.FilterCapsule" parent="Widget.MaterialComponents.Button"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">40dp</item> <item name="android:layout_marginEnd">8dp</item> <item name="cornerRadius">14dp</item> <item name="android:checkable">true</item> <item name="iconGravity">textStart</item> <item name="android:textStyle">normal</item> <item name="android:textAllCaps">false</item> <item name="iconTint">@drawable/category_filter_foreground</item> <item name="backgroundTint">@drawable/category_filter_background</item> <item name="android:textColor">@drawable/category_filter_foreground</item> </style>`

Android API version: 29

Material Library version: 1.2.0-aplpha05

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

26reactions
gabrielemariotticommented, Aug 2, 2020

You can’t assign a style using: MaterialButton(wrap(context, attrs, defStyleAttr, defStyleRes), attrs, defStyleAttr)

TheMaterialThemeOverlay.wrapmethod uses the materialThemeOverlay attribute to create a themed context.

You apply a theme overlay using something like:

class AccentButton @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        @AttrRes defStyleAttr: Int = R.attr.materialButtonStyle,
        @StyleRes defStyleRes: Int = R.style.AccentButtonThemeOverlay
) : MaterialButton(ContextThemeWrapper(context, defStyleRes), attrs, defStyleAttr) {
}

with:

    <style name="AccentButtonThemeOverlay" parent="">
        <item name="materialThemeOverlay">@style/buttonoverlay</item>
    </style>

    <style name="buttonoverlay">
        <item name="colorPrimary">@color/...</item>
    </style>

If you want to create a custom button with a custom style you have to:

  • define an attribute in attrs.xml <attr name="myButtonStyle" format="reference"/>
  • assign in your app theme a value to this new attr:
    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="myButtonStyle">@style/AccentButtonStyle</item>
   </style>

with:

    <style name="AccentButtonStyle" parent="Widget.MaterialComponents.Button">
        <item name="backgroundTint">@color/...</item>
        <item name="icon">@drawable/....</item>
        <item name="iconTint">@color/....</item>
    </style>

and then use this constructor:

class AccentButton @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        @AttrRes defStyleAttr: Int = R.attr.myButtonStyle
  ) : MaterialButton(context, attrs, defStyleAttr) {
}
2reactions
alapshincommented, Jun 4, 2020

I have created repo that demonstrates this problem: https://github.com/alapshin/materialissue1183.

Screenshot that demonstrates it. First button uses style specified in xml, second button specifies style as constructor parameter

class AccentButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    @AttrRes defStyleAttr: Int = R.attr.materialButtonStyle,
    @StyleRes defStyleRes: Int = R.style.AccentButtonStyle
) : MaterialButton(wrap(context, attrs, defStyleAttr, defStyleRes), attrs, defStyleAttr) {
}

device-2020-06-04-104111

Read more comments on GitHub >

github_iconTop Results From Across the Web

Apply Style to MaterialButton programmatically - Stack Overflow
The only workaround I've found so far is to set the tint programmatically like: button.setBackgroundTintList(ColorStateList.valueOf(Color.
Read more >
Set MaterialButton style to TextButton programmatically-kotlin
After reading the material design source, I discovered the following. The third parameter to MaterialButton is not a style resource but a style...
Read more >
MaterialButton - Android Developers
A convenience class for creating a new Material button. This class supplies updated Material styles for the button in the constructor.
Read more >
Android Material Design Button Style Design - DigitalOcean
The Button with the style Borderless doesn't have the textcolor set from the theme, though the textColor attribute is present in the theme....
Read more >
How to Dynamically Change an Android View's Style - Medium
The reason this isn't possible is that styles, by default, are set through ... apply styles programmatically to Android views, including custom attributes....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found