Search code examples
androidandroid-textinputlayout

TextInputLayout label to achor above the left drawable of an EditText


Is it possible to make the TextInputLayout label to show above the left drawable of an EditText perpendicularly when user focuses or types in the EditText.

Here is the xml of the EditText:

 <android.support.design.widget.TextInputLayout
                android:id="@+id/completion_date_layout2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <EditText
                    android:id="@+id/etTaskDate"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:hint="@string/title_completion_date"
                    android:inputType="text"
                    android:drawableLeft="@drawable/ic_date"
                    android:paddingBottom="15dp"
                    android:drawablePadding="5dp"
                    android:textSize="@dimen/fields_text_size"/>
            </android.support.design.widget.TextInputLayout>

Here is the desired output:

enter image description here

Here is the output that I am getting:

enter image description here


Solution

  • Thanks to Java's member access model and Google's developers who left a small loophole it could be achieved with a simple subclassing which repeats a minimum of the original code:

    package android.support.design.widget;
    
    import android.content.Context;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    
    public final class TextInputLayoutEx extends TextInputLayout {
    
        private final int mDefaultPadding = __4DP__;
        private final Rect mTmpRect = new Rect();
    
        public TextInputLayoutEx(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            if (isHintEnabled() && mEditText != null) {
                final Rect rect = mTmpRect;
                ViewGroupUtils.getDescendantRect(this, mEditText, rect);
                mCollapsingTextHelper.setCollapsedBounds(
                    rect.left + mDefaultPadding, getPaddingTop(),
                    rect.right - mDefaultPadding, bottom - top - getPaddingBottom());
                mCollapsingTextHelper.recalculate();
            }
        }
    
    }
    

    Here we put a new class to the same package which opens an access to the mCollapsingTextHelper with a package-level visibility and then repeat part of the code from the original onLayout method which manages field name positioning. The __4DP__ value is 4dp value converted to pixels, I'm pretty sure everyone has an utility method for this.

    In your xml layout just switch from the android.support.design.widget.TextInputLayout to android.support.design.widget.TextInputLayoutEx so your layout looks like this:

    <android.support.design.widget.TextInputLayoutEx
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Mobile">
        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/ic_phone_black_24dp"
            android:drawablePadding="4dp"/>
    </android.support.design.widget.TextInputLayoutEx>
    

    And the result is

    Collapsed and expanded state

    At the moment it works for com.android.support:design:25.3.1