After reading the material design source, I discovered the following. The third parameter to MaterialButton
is not a style resource but a style attribute. The parameter is called defStyleAttr
and not defStyleRes
, only the second one is equivalent to passing style
in the XML file. And MaterialButton
do not implement the 4 parameters constructor which takes this.
To clarify, a style resource is a "standalone" style definition, a style attribute is the name of the attribute in the context style. It is a bit weird that you are supposed to style a whole widget with one attribute, but this is how it works.
This means, we have to create and attribute that references the whole widget style and pass it when creating our button.
To do this, we have to:
- Create an
attr
resource in the app resources, by adding <attr name="myAttr" format="reference"/>
to styles.xml
.
- Still in
styles.xml
, modify the app theme to use the attribute, like this:
<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar">
<item name="myAttr">@style/Widget.MaterialComponents.Button.TextButton</item>
</style>
- Use the attribute when creating the button, like so:
val errorBtn = MaterialButton(this, null, R.attr.myAttr)
This will work only if this
(current context, usually an activity) has AppTheme
applied to it (which should generally be the case). If this is not the case, or if you want to change the theme, it can be applied with ContextThemeWrapper
, like so:
val ctx = ContextThemeWrapper(this, R.style.AppTheme)
val errorBtn = MaterialButton(ctx, null, R.attr.myAttr)