Is it possible to programmatically create a material view (e.g. button) and use a defined style so that it looks like when created by a layout?

45 views Asked by At

We get different XML-strings from some JNI-calls that are representing specific layouts that we are currently parsing on our own and than creating the related view objects programmatically and setting all the specific configurations.

Button bt = new Button(activityMain);
bt.setTag(tag);
bt.setLayoutParams(params);
bt.setTextColor(color);

The challenge that we now have is, that we want to use the styles that we have defined on java side. Therefore we extract the value of the "style" attribute from the given XML-string and are searching for the related resource id and than use it as the 4-th argument in the constructor.

int styleID = activityMain.getResources().getIdentifier(
    styleName,
    "style",
    activityMain.getPackageName()
);

Button bt = new Button(activityMain, null, 0, styleID);

The problem here is, that sadly not all views (that we have currently implemented in our own parser) are supporting the 4-argument constructor, like MaterialButton or AppCompatTextView and many more.

So i tried to use the 3-argument constructor for MaterialButton. If i understood correctly the 3-th argument defines some item / attribute from my chosen theme which references some style.

Therefore i added for testing purpose one custom attribute and set it up like the following:

// attrs.xml

<attr name="myButtonStyle" format="reference" />
// themes.xml

<style name="myTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    ...
    <item name="myButtonStyle">@style/myButtonStyle</item>
</style>
// styles.xml

<style name="myButtonStyle">
    <item name="android:backgroundTint">@color/my_primary100</item>
    <item name="android:textColor">@color/white100</item>
</style>
// myFile.java

MaterialButton bt = new MaterialButton(activityMain, null, R.attr.myButtonStyle);

But i ended in a situation where not all settings of the style were adopted and the button looked different than when i create it by inflating from some predefined layout which uses exactly the same style.

// myLayout.xml

<com.google.android.material.button.MaterialButton
    android:id="@+id/btLogin"
    style="@style/myButtonStyle"
    android:text="Anmelden" />

While searching for other ways to do this i found an issue to this topic on github: Creating a button with a style programmatically does not set all attributes

The difference that i see here is, that the style in the solution example has some parent:

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

Is this the reason why it does not work correct on my side? Does the referenced style in my theme really need to define the material style as a parent to adopt all settings?

Isn't there another solution to solve my "challenge"? Because the style that i reference can be also used by other views, not only by material ones. So i can't always put a parent in there.

I am also open for other ideas :-)

0

There are 0 answers