问题
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
回答1:
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>
回答2:
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.
来源:https://stackoverflow.com/questions/56044075/overriding-edittextstyle-doesnt-work-with-latest-material-components-base-style