Search code examples
androidlayoutmaterial-design

TextInputLayout label interferring with entered text


In my new Android app, the label of the TextInputLayout appears in the space where the user types the input. This causes the entered text to render on top of the label/hint:

When the user first loads the page: When the user first loads the page

When the user taps on the text input, the label shrinks towards the top left as expected: When the user taps on the text input

When the user types an entry, it types over the label: When the user types an entry

I have two questions:

  1. What is the appropriate behavior here following Material Design guidelines?
  2. How do I accomplish this behavior?

Here is my layout file:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:theme="@style/Theme.JobSearch"
    tools:context=".ui.JobsDetailsFragment">

    <TextView
        android:id="@+id/text_new_position"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/new_position"
        android:theme="@style/Theme.JobSearch"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_new_position">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/text_title"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:hint="@string/title"
            android:theme="@style/Theme.JobSearch"
            app:layout_constraintTop_toTopOf="parent" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.JobSearch"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textInputLayout">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/text_business_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/business_name" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/position_save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:contentDescription="@string/position_save"
        android:src="@drawable/done"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Update

I tried moving android:hint to the TextInputLayout and still see the same behavior:

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/title_input_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/title"
        android:theme="@style/Theme.JobSearch"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_new_position">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/text_title"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintTop_toTopOf="parent" />
    </com.google.android.material.textfield.TextInputLayout>

For reference, here is themes.xml:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.JobSearch" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/white</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>

    <style name="Theme.JobSearch.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="Theme.JobSearch.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="Theme.JobSearch.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

Solution

  • I have replicated your issue and the problem is because your using android:theme="@style/Theme.JobSearch" in your TextInputLayout or TextInputEditText. Remove all android:theme attributes from all TextInputLayout and TextInputEditText and use your own style instead which will be applied only to your TextInputLayout like style="@style/MyTextInputLayoutStyle".

    I have modified your xml layout using a custom style for each TextInputLayout like below:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:theme="@style/Theme.JobSearch"
        tools:context=".ui.JobsDetailsFragment">
    
        <TextView
            android:id="@+id/text_new_position"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/new_position"
            android:theme="@style/Theme.JobSearch"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/textInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/title"
            style="@style/MyTextInputLayoutStyle"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_new_position">
    
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/text_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </com.google.android.material.textfield.TextInputLayout>
    
        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/business_name"
            style="@style/MyTextInputLayoutStyle"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textInputLayout">
    
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/text_business_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.google.android.material.textfield.TextInputLayout>
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/position_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/fab_margin"
            android:contentDescription="@string/position_save"
            android:src="@drawable/done"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    where style="@style/MyTextInputLayoutStyle" is your custom style for the TextInputLayout like below:

    <style name="MyTextInputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
        <item name="boxStrokeColor">@color/text_input_box_stroke_color</item>
        <item name="boxBackgroundColor">@android:color/white</item>
    </style>
    

    and i have set a color selector for your boxStrokeColor (@color/text_input_box_stroke_color) to change the underline bottom stroke color based on the focused/default state like below:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@color/teal_200" android:state_focused="true" />
        <item android:color="@color/teal_200" android:state_hovered="true" />
        <item android:color="@android:color/darker_gray" />
    </selector>
    

    And the final result after the above changes will be like this:

    textInputLayout