Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply Style to MaterialButton programmatically

I'm trying to create a custom view extending from MaterialButton and apply style in code so I don't need to do it in xml.

class CustomRedButton @JvmOverloads constructor(
    context: Context, 
    attrs: AttributeSet? = null, 
    defStyleAttr: Int = 0
) : MaterialButton(ContextThemeWrapper(context, R.style.ButtonRedStyle), attrs, defStyleAttr) 

Style is:

<style name="ButtonRedStyle" 
    parent="Widget.MaterialComponents.Button.TextButton">
    <item name="backgroundTint">@color/red</item>
    <item name="rippleColor">@color/grey</item>
    <item name="strokeWidth">1dp</item>
    <item name="strokeColor">@color/black</item>
</style>

Everything works fine but backgroundTint property. For some reason background color is not changing, and it has Theme's primary color. However, if I try to apply the style to a MaterialButton in xml it does change the color.

Any idea why that can be happening or how I can achieve it?

like image 926
evaristokbza Avatar asked Sep 19 '18 08:09

evaristokbza


3 Answers

Using

MaterialButton(ContextThemeWrapper(context, R.style.ButtonRedStyle), attrs, defStyleAttr)

you are applying a themeoverlay to default style, you are not applying a different style.

It means:

<style name="ButtonRedTheme" parent="...">
    <item name="colorPrimary">@color/...</item>
    <item name="colorOnPrimary">@color/...</item>
    <item name="colorSecondary">@color/...</item>
</style>

If you want to apply a different style you have to:

  • Define a custom attribute in attrs.xml
    <attr name="myButtonStyle" format="reference"/>
  • Assing a style to this attribute in your app theme:
   <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="myButtonStyle">@style/CustomButtonStyle</item>
   </style>
  • Define the custom style:
    <style name="CustomButtonStyle" parent="Widget.MaterialComponents.Button.*">
        <item name="backgroundTint">@color/...</item>
        <item name="rippleColor">@color/grey</item>
        <item name="strokeWidth">1dp</item>
        <item name="strokeColor">@color/black</item>
    </style>

Finally use:

val customButton = MaterialButton(context, null, R.attr.myButtonStyle)
like image 133
Gabriele Mariotti Avatar answered Nov 17 '22 22:11

Gabriele Mariotti


I'm also facing the same issue. The only workaround I've found so far is to set the tint programmatically like:

button.setBackgroundTintList(ColorStateList.valueOf(Color.RED));
like image 10
Zheko Avatar answered Nov 17 '22 22:11

Zheko


If you want to change your style for CustomView, you've to pass it to constructor by passing it into third param defStyleAttr like this:

class CustomRedButton @JvmOverloads constructor(
    context: Context, 
    attrs: AttributeSet? = null, 
    defStyleAttr: Int = R.style.ButtonRedStyle // Just default style like this
) : MaterialButton(context, attrs, defStyleAttr)

and you can initialize it like this programmatically,

CustomRedButton(this, null, R.style.ButtonRedStyle) // Initialization, ('this' is context)

For more details refer here

like image 2
Jeel Vankhede Avatar answered Nov 18 '22 00:11

Jeel Vankhede