Reputation: 1430
I'd like to create a MaterialButton
programmatically and use the TextButton
style on it.
I tried the following but the resulting button has a background color and is not a TextButton
.
val newContext = ContextThemeWrapper(this, R.style.Widget_MaterialComponents_Button_TextButton)
val errorBtn = MaterialButton(newContext, null, R.style.Widget_MaterialComponents_Button_TextButton)
I tried many variants, (without using the 3 parameters constructor or without context wrapper).
I found this question: Apply Style to MaterialButton programmatically
But the answer is not satisfying as the setting background tint do not produce good results (there is a shadow being the button).
Upvotes: 7
Views: 2723
Reputation: 1430
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:
attr
resource in the app resources, by adding <attr name="myAttr" format="reference"/>
to styles.xml
.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>
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)
Upvotes: 7