Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding editTextStyle doesn't work with latest Material Components base style

In an app of mine, I'm using the Theme.MaterialComponents.Light.NoActionBar as a base style. In this style, which I call AppTheme, I'm trying to override editTextStyle to provide a custom style for com.google.android.material.textfield.TextInputEditText (according to the source code, it uses R.attr.editTextStyle as a default style).

This is my current theme, related to the TIEditText and TILayout:

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    [ primary and secondary colors, OnColors, etc.]
    <item name="editTextStyle">@style/AppTheme.TextInputEditText</item>
    <item name="textInputStyle">@style/AppTheme.TextInputLayout</item>

    [ Custom attribute for testing, defined in attrs.xml ]
    <item name="textInputEditTextStyle">@style/AppTheme.TextInputEditText</item>
</style>

For some reason, even though I set editTextStyle, if I use it in code, it does not get applied:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/tilFirstName"
    style="?attr/textInputStyle"
    android:hint="@string/label_firstname"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/firstName"
        style="?attr/editTextStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:text="@={viewModel.firstName}" />
</com.google.android.material.textfield.TextInputLayout>

However if I replace the style of firstName with ?attr/textInputEditTextStyle, it works.

Why can't I override editTextStyle in the default theme? What the hell is going on?

Target SDK is 28, minSDK is 21, Material library version is 1.1.0-alpha06

like image 243
fonix232 Avatar asked May 08 '19 15:05

fonix232


2 Answers

Let's just move past the part where we all recognize that Android themes and styles are singularly the most absurd wasteland of hackery and guesswork ever devised by human beings.

This is an expansion on the previous answer. Same silly 'hack'. I was able to style the TextInputEditText by setting editTextStyle, but not where it intuitively belongs, but rather inside a custom materialThemeOverlay nested within the style defined for textInputStyle. Witness:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
    <!-- works fine -->
    <item name="textInputStyle">@style/AppTheme.TextInputLayoutStyle</item>
    <!-- should work fine, doesn't work, happily ignored -->
    <!-- <item name="editTextStyle">@style/AppTheme.TextInputEditTextStyle</item> -->
</style>

<style name="AppTheme.TextInputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
    <!-- other props (boxBackgroundMode, boxBackgroundColor, boxStrokeColor, etc) -->
    <!-- can we set editTextStyle from here? Of course not! We should magically know we need a material theme overlay-->
    <item name="materialThemeOverlay">@style/AppTheme.MaterialThemeOverlay</item>
</style>

<!-- style inception! a style, child of another style, whose only purpose is to refer to yet another style -->
<style name="AppTheme.MaterialThemeOverlay">
    <item name="editTextStyle">@style/AppTheme.TextInputEditTextStyle</item>
</style>

<!-- finally, the style we SHOULD have been able to set from the theme -->
<style name="AppTheme.TextInputEditTextStyle" parent="@style/Widget.MaterialComponents.TextInputEditText.OutlinedBox">
    <item name="android:textColor">@color/white</item>
</style>

All of the above ridiculousness and ANOTHER day of my life thrown in the trash, just to change the color of text. Thaaaaanks Aaaaaandroid.

like image 191
rmirabelle Avatar answered Jan 02 '23 20:01

rmirabelle


For some reason, even though I set editTextStyle, if I use it in code, it does not get applied

It happens because the default styles of the TextInputLayout override the editTextStyle using the materialThemeOverlay attribute.

For example the Widget.MaterialComponents.TextInputLayout.FilledBox has this default style:

<style name="Widget.MaterialComponents.TextInputLayout.FilledBox" parent="Base.Widget.MaterialComponents.TextInputLayout">
    <item name="materialThemeOverlay">
       @style/ThemeOverlay.MaterialComponents.TextInputEditText.FilledBox
    </item>
    ....
</style>
<style name="ThemeOverlay.MaterialComponents.TextInputEditText.FilledBox">
    <item name="editTextStyle">@style/Widget.MaterialComponents.TextInputEditText.FilledBox</item>
</style>
like image 30
Gabriele Mariotti Avatar answered Jan 02 '23 19:01

Gabriele Mariotti