Change font of the floating label EditText and TextInputLayout

30.6k views Asked by At

Someone tried to change the font of the floating label? I changed the source of EditText but the font of the floating label did not change, I am very grateful to those who help me

Code:

               <android.support.design.widget.TextInputLayout
                    android:id="@+id/tilTextoDescricao"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_toRightOf="@id/tilValorUnidade"
                    android:layout_marginTop="10dp">

                    <EditText
                        android:id="@+id/etTextoDescricao"
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="5dp"
                        android:hint="Descrição"
                        android:textSize="15dp"
                        android:inputType="text" />

                </android.support.design.widget.TextInputLayout>

----------------- 

   etTextoDescricao= (EditText) findViewById(R.id.etTextoDescricao);
  etTextoDescricao.setTypeface(CustomTypeface.getTypefaceMediumDefault(this));

enter image description here

12

There are 12 answers

4
adneal On

Unfortunately, you'll have to use reflection to handle this.

The floating label is drawn by CollapsingTextHelper, which is an internal, package-private class and isn't setup to handle spans. So, using something like a custom TypefaceSpan won't work in this case.

Because this uses reflection, it isn't guaranteed to work in the future.

Implementation

final Typeface tf = Typeface.createFromAsset(getAssets(), "your_custom_font.ttf");
final TextInputLayout til = (TextInputLayout) findViewById(R.id.yourTextInputLayout);
til.getEditText().setTypeface(tf);
try {
    // Retrieve the CollapsingTextHelper Field
    final Field cthf = til.getClass().getDeclaredField("mCollapsingTextHelper");
    cthf.setAccessible(true);

    // Retrieve an instance of CollapsingTextHelper and its TextPaint
    final Object cth = cthf.get(til);
    final Field tpf = cth.getClass().getDeclaredField("mTextPaint");
    tpf.setAccessible(true);

    // Apply your Typeface to the CollapsingTextHelper TextPaint
    ((TextPaint) tpf.get(cth)).setTypeface(tf);
} catch (Exception ignored) {
    // Nothing to do
}

Error view

If you needed to change the font of the error, you could do one of two things:

  1. Use Reflection grab the error TextView and apply the Typeface much like before
  2. Use a custom span. Unlike the floating label, the error view used by TextInputLayout is just a TextView, so it's able to handle spans.

Using reflection

final Field errorField = til.getClass().getDeclaredField("mErrorView");
errorField.setAccessible(true);
((TextView) errorField.get(til)).setTypeface(tf);

Using a custom span

final SpannableString ss = new SpannableString("Error");
ss.setSpan(new FontSpan(tf), 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
til.setError(ss);

private static final class FontSpan extends MetricAffectingSpan {

    private final Typeface mNewFont;

    private FontSpan(Typeface newFont) {
        mNewFont = newFont;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setTypeface(mNewFont);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        paint.setTypeface(mNewFont);
    }

}

Results

results

The font I'm using is Smoothie Shoppe.

0
zohaib khaliq On

This is how i achieve this

edit_login_emailOrPhone.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
            {
                textInputLayout_login_emailOrPhone.setTypeface(APSApplication.getInstance().getFonts().getTypefaceSemiBold());
            }else
            {
                textInputLayout_login_emailOrPhone.setTypeface(APSApplication.getInstance().getFonts().getTypefaceRegular());
            }
        }
    });
0
Isao Nokarikashi On

In case you too met an exotic requirement to set custom font ONLY to the floating label, and anything else didn't work for you as well, try this. This worked for me, at least for material lib ver. 1.3.0-alpha03.

@SuppressLint("RestrictedApi")
fun setHintFontFamily(view: TextInputLayout, fontRes: Int) {
    val font = ResourcesCompat.getFont(view.context, fontRes)!!

    try {
        val collapsingTextHelperField =
            view::class.java.getDeclaredField("collapsingTextHelper").apply {
                isAccessible = true
            }
        val collapsingTextHelper = collapsingTextHelperField.get(view) as CollapsingTextHelper

        collapsingTextHelper.collapsedTypeface = font
    } catch (e: Exception) {
    }
}

First we get the CollapsingTextHelper as in some other answers, but then we use its property collapsedTypeface that seems to do exactly what we need -- apply a font only to the floating label. Please note that this property's visibility is restricted to library group (that's why I used @SuppressLint). So the implementation details might change in the future.

0
Ehsan Mashhadi On

Use can use style.xml like below:

Style file:

<style name="TextInputLayoutErrorStyle" parent="TextAppearance.Design.Error">
    <item name="fontFamily">@font/iran_sans_medium</item>
    <item name="android:fontFamily">@font/iran_sans_medium</item>
</style>

<style name="TextInputLayoutHintStyle" parent="TextAppearance.Design.Hint">
    <item name="fontFamily">@font/iran_sans_medium</item>
    <item name="android:fontFamily">@font/iran_sans_medium</item>
</style>

<style name="TextInputLayoutHelperStyle" parent="TextAppearance.Design.HelperText">
    <item name="fontFamily">@font/iran_sans_medium</item>
    <item name="android:fontFamily">@font/iran_sans_medium</item>
</style>

<style name="TextInputLayoutOutlinedBoxStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
    <item name="helperTextTextAppearance">@style/TextInputLayoutHelperStyle</item>
    <item name="errorTextAppearance">@style/TextInputLayoutErrorStyle</item>
    <item name="hintTextAppearance">@style/TextInputLayoutHintStyle</item>
</style>

Layout file:

<com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_centerInParent="true"
            android:hint="@string/cardname_hint"
            android:layout_marginStart="30dp"
            android:layout_marginEnd="30dp"
            card_view:helperText="@string/cardname_helper"
            style="@style/TextInputLayoutOutlinedBoxStyle"
            android:layout_height="wrap_content">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:fontFamily="@font/iran_sans_medium"
                android:textColor="@color/colorTextPrimary"
                android:layout_height="wrap_content" />

</com.google.android.material.textfield.TextInputLayout>
1
Aleksandar Ilic On

Here is a custom class implementation for adneal's answer.

public class CustomTextInputLayout extends TextInputLayout {

    public CustomTextInputLayout(Context context) {
        super(context);
        initFont(context);
    }

    public CustomTextInputLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initFont(context);
    }

    private void initFont(Context context) {
        final Typeface typeface = Typeface.createFromAsset(
                context.getAssets(), "fonts/YOUR_CUSTOM_FONT.ttf");

        EditText editText = getEditText();
        if (editText != null) {
            editText.setTypeface(typeface);
        }
        try {
            // Retrieve the CollapsingTextHelper Field
            final Field cthf = TextInputLayout.class.getDeclaredField("mCollapsingTextHelper");
            cthf.setAccessible(true);

            // Retrieve an instance of CollapsingTextHelper and its TextPaint
            final Object cth = cthf.get(this);
            final Field tpf = cth.getClass().getDeclaredField("mTextPaint");
            tpf.setAccessible(true);

            // Apply your Typeface to the CollapsingTextHelper TextPaint
            ((TextPaint) tpf.get(cth)).setTypeface(typeface);
        } catch (Exception ignored) {
            // Nothing to do
        }
    }
}

In your XML files now you need to use CustomTextInputLayout instead of TextInputLayout and it will work out of the box.

<your.package.CustomTextInputLayout
    android:id="@+id/textInputLayout_email"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <AutoCompleteTextView
        android:id="@+id/editText_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint_email"
        android:inputType="textEmailAddress" />

Thanks adneal for the answer.

3
Ali Sardari On
final Typeface tf = Typeface.createFromAsset(getAssets(), "your_custom_font.ttf");
final TextInputLayout til = (TextInputLayout) findViewById(R.id.yourTextInputLayout);
til.getEditText().setTypeface(tf);
til.setTypeface(tf);
0
Lucas Orso On

I was looking for this, I found this way, using the support library:

Typeface typeface = ResourcesCompat.getFont(context, R.font.myfont);

and set this typeface to yout TextInpuLayout.

For me works like charm, I hope it helps others =]

Source: Documentation

2
azizbekian On

I'm using new MaterialComponents theme and none of the answers helped me.

Had to play with styles and themes on my own. Will post a chunk of styles here in case somebody faces the same issue.

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
  ...
  <item name="textInputStyle">@style/CustomFontTextInputLayout</item>
</style>  

<!-- region TextInputLayout & TextInputEditText styles -->
<style name="TextInputLayout.OutlineBox.CustomFont" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
  <item name="android:theme">@style/ThemeOverlay.TextInputEditText.OutlinedBox.CustomFont</item>
</style>

<style name="ThemeOverlay.TextInputEditText.OutlinedBox.CustomFont" parent="ThemeOverlay.MaterialComponents.TextInputEditText.OutlinedBox">
  <item name="editTextStyle">@style/TextInputEditText.OutlinedBox.CustomFont</item>
</style>

<style name="TextInputEditText.OutlinedBox.CustomFont" parent="Widget.MaterialComponents.TextInputEditText.OutlinedBox">
  <item name="android:fontFamily">@font/my_font</item>
</style>

<style name="CustomFontTextInputLayout" parent="Widget.Design.TextInputLayout">
  <item name="hintTextAppearance">@style/TextInputLayoutHintText</item>
  <item name="helperTextTextAppearance">@style/TextInputLayoutHelperText</item>
  <item name="errorTextAppearance">@style/TextInputLayoutErrorText</item>
</style>

<style name="TextInputLayoutHintText" parent="TextAppearance.Design.Hint">
  <item name="android:fontFamily">@font/my_font</item>
</style>

<style name="TextInputLayoutHelperText" parent="TextAppearance.Design.HelperText">
  <item name="android:fontFamily">@font/my_font</item>
</style>

<style name="TextInputLayoutErrorText" parent="TextAppearance.Design.Error">
  <item name="android:fontFamily">@font/my_font</item>
</style>
<!-- endregion -->

Then in xml layout:

<android.support.design.widget.TextInputLayout
    style="@style/TextInputLayout.OutlineBox.CustomFont"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/first_name"/>
</android.support.design.widget.TextInputLayout>

Here's the result:

enter image description here

0
Danish Ajaib On

There is a simpler way,

Create a new directory in your 'res' folder named 'font' and put a font in there. Then open your 'styles' file and create a new style :

<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
        <item name="android:fontFamily">@font/poppins_regular</item>
    </style>

You can add more properties as well, such as textColor, textSize etc..

Then in your XML:

<android.support.design.widget.TextInputLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:hintTextAppearance="@style/customfontstyle"
       >

        <android.support.design.widget.TextInputEditText
            android:layout_width="220dp"
            android:layout_height="wrap_content"
            android:id="@+id/edit_phone_number"
            android:hint="@string/phone_number_label"

            android:inputType="number"
            />
    </android.support.design.widget.TextInputLayout>

I checked it and it works.

2
Austyn Mahoney On

As of Design Library v23, you can use TextInputLayout#setTypeface().

This will set the typeface on both the expanded and floating hint.

Here is the feature request where it was discussed on b.android.com.

EDIT: The error view typeface was not being set, but is now fixed in v25.1.0.

1
imansdn On

i just found a simple solution and it's worked for me:

in this way you can set the typeface to hint of any edit text:

in layout.xml :

 <android.support.design.widget.TextInputLayout
            android:id="@+id/text_input1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:id="@+id/edt_user"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/username"/>
        </android.support.design.widget.TextInputLayout>

and in java class :

public class MainActivity extends AppCompatActivity {

EditText editText;
TextInputLayout textInputLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Typeface font_yekan= Typeface.createFromAsset(getAssets(), "fonts/byekan.ttf");
        textInputLayout= (TextInputLayout) findViewById(R.id.text_input1);
    textInputLayout.setTypeface(font_yekan);
      }
 }
0
Ashkan Ghodrat On

fixing a problem in @adneal answer: if setErrorEnabled is not set true, mErrorView would be null and if you set it false at any point the font would change back to default. so to fix it:

in you custom TextInputLayout override setErrorEnabled

@Override
public void setErrorEnabled(boolean enabled) {

    super.setErrorEnabled(enabled);

    if (enabled) {

        try {

            Field cthf = TextInputLayout.class.getDeclaredField("mErrorView");
            cthf.setAccessible(true);

            TextView error = (TextView) cthf.get(this);

            if (error != null)
                error.setTypeface(tf);


        } catch (Exception e) {

        }
    }
}