Cheok Yan Cheng Cheok Yan Cheng - 1 month ago 24
Android Question

Is it possible to have different font for floating text and hint text of InputTextLayout

Currently, I would like to have a bold effect on my floating text of

InputTextLayout
. Here's what I'm doing

this.usernameTextInputLayout.setTypeface(Utils.ROBOTO_BOLD_TYPE_FACE);


It works as expected. The floating text (Username) has became bold.

enter image description here

However, this will create another undesired effect for me. The hint text will become bold as well.

enter image description here

You can compare the above 2 images. Please take note, for comparison purpose, I just leave
passwordTextInputLayout
as it is.

Is it possible to have different fonts, for floating text and hint text of
InputTextLayout
?

Answer

As you know, TextInputLayout uses a private helper class to handle the hint text stylings and animations. This class - CollapsingTextHelper - maintains separate typefaces for its collapsed and expanded states. We just need to set the right one, which we'll do using reflection.

I usually package these kinds of functionalities into custom subclasses, so I'll do the same here. If you don't want to use a subclass, the reflection stuff could be easily pulled into some simple methods you can put in your Activity or utility class.

public class CustomTextInputLayout extends TextInputLayout {

    private Object collapsingTextHelper;
    private Method setCollapsedTypefaceMethod;
    private Method setExpandedTypefaceMethod;

    public CustomTextInputLayout(Context context) {
        this(context, null);
    }

    public CustomTextInputLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    private void init() {
        try {
            Field cthField = TextInputLayout.class
                .getDeclaredField("mCollapsingTextHelper");
            cthField.setAccessible(true);
            collapsingTextHelper = cthField.get(this);

            setCollapsedTypefaceMethod = collapsingTextHelper
                .getClass().getDeclaredMethod("setCollapsedTypeface", Typeface.class);
            setCollapsedTypefaceMethod.setAccessible(true);

            setExpandedTypefaceMethod = collapsingTextHelper
                .getClass().getDeclaredMethod("setExpandedTypeface", Typeface.class);
            setExpandedTypefaceMethod.setAccessible(true);
        }
        catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
            collapsingTextHelper = null;
            setCollapsedTypefaceMethod = null;
            setExpandedTypefaceMethod = null;
            e.printStackTrace();
        }
    }

    public void setCollapsedTypeface(Typeface typeface) {
        if (collapsingTextHelper == null) {
            return;
        }

        try {
            setCollapsedTypefaceMethod.invoke(collapsingTextHelper, typeface);
        }
        catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void setExpandedTypeface(Typeface typeface) {
        if (collapsingTextHelper == null) {
            return;
        }

        try {
            setExpandedTypefaceMethod.invoke(collapsingTextHelper, typeface);
        }
        catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

Somewhat counterintuitively, TextInputLayout's collapsed state is when the hint is the floating label above the EditText. Its expanded state is when the hint is in the "normal" position, inside the EditText. Methods to set the typeface for both states are given above.

This is a drop-in replacement for TextInputLayout, and you can use it in your layouts just as you would that. For example:

<com.scension.til.CustomTextInputLayout
    android:id="@+id/username_til"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:hintTextAppearance="@style/TextLabel">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:hint="Username" />

</com.scension.til.CustomTextInputLayout>

In your code, to set the typeface of the floating text hint:

CustomTextInputLayout usernameTextInputLayout =
    (CustomTextInputLayout) findViewById(R.id.username_til);

usernameTextInputLayout.setCollapsedTypeface(Utils.ROBOTO_BOLD_TYPE_FACE);
Comments