Search code examples
androidandroid-edittextandroid-themeandroid-styles

Why EditText only accepts Theme?


I was trying to apply a style to an EditText to change it's colorAccent, I tried to set its style and android:textAppearance, but it completely ignored my new settings. The only way I got it to work was by setting its android:theme.

Am I doing something wrong or is this expected behavior? Why?

My style:

<style name="bright_color_cursor" parent="AppTheme">
    <item name="colorAccent">@color/primaryBrightColor</item>
    <item name="android:textColorHighlight">@color/primaryBrightColor</item>
</style>

My EditText:

<EditText
    android:id="@+id/edit_text"
    android:theme="@style/bright_color_cursor"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:layout_marginBottom="16dp"
    android:background="@android:color/transparent"
    android:ems="10"
    android:hint="@string/hello"
    android:inputType="textCapWords"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="@+id/name_edit_text"
    app:layout_constraintTop_toBottomOf="@+id/divider" />

Changing android:theme to any of this settings won't work:

style="@style/bright_color_cursor"

or

android:textAppearance="@style/bright_color_cursor"

Solution

  • Yep, this behavior is to be expected with an EditText. We need to style it by using the android:theme property.

    When using @style, the EditText doesn't use the values that we set (and thus the style seems to be ignored). This is, because the EditText creates some children views that are not being styled. See my detailed explanation below.


    Detailed explanation and the cause

    1) First, the meanings of the options tried and what these do:

    • style: (Note: not prefixed with android:): This sets the styles only for the component itself and does not change the styles of it's underlying children views/layouts.
    • android:theme: This basically applies to style to itself and applies the style to it's children views/layouts.
    • android:textAppearance: This one behaves just like @style for styling.

    2) The EditText functionality

    As we can imagine: an EditText is not just a simple view. It has a background drawable and handles interaction and such. It simply needs some additional views (and logic) for this functionality to work.

    For the functionality of the EditText, it adds some subviews as children to be able to do what we expect from it.

    3) Back to theming

    The subviews that the EditText adds to do it's functionality, are styled just like the other views are being styled. Which means that the child views only inherit the style when we use the android:theme property. Because this property causes it to style the children views too.

    And, if we use @style on the edittext, the children will not get this style.

    4) Why this happens (only) for EditText?

    Well, not really only... The base view of an EditText is a TextView, but a TextView doesn't provide the functionality that an EditText needs. So the EditText adds additional functionality itself.

    A Button for example has the TextView as base too. But this class has enough views with the text and background it gets from the base class, and thus a Button doesn't need to add additional views for it's functionality. So for this, using @style works as it creates no children views to style.

    Having said this, a small remark: In fact, in the source the TextView actually contains the editting logic, but in case of a Button it simply doesn't execute that part of code. (A button doesn't need the Editting functionality, thus it's not being executed)